[Checkins] SVN: grok/branches/darrylcousins-martian-layers/ Grok-Martian-Layer Branch

Darryl Cousins darryl at darrylcousins.net.nz
Tue Jun 26 09:10:55 EDT 2007


Log message for revision 77094:
  Grok-Martian-Layer Branch
  =========================
  
  * merged the mcweekly layer branch to the martian branch.
  * changed the buildout to use eggs
  * unit tests all pass
  * functional tests pass - cp ./ftesting.zcml to ./parts/test
  
  Bugs
  ====
  
  * find out how to include ftesting file in parts/test with the buildout
  * in ftests/static/simple_fixture/ellie I needed to define grok.context on all
    views
  
  
    To Do
    =====
  
    * start bringing z3c.form into the play
  
  

Changed:
  A   grok/branches/darrylcousins-martian-layers/
  A   grok/branches/darrylcousins-martian-layers/COPYRIGHT.txt
  A   grok/branches/darrylcousins-martian-layers/CREDITS.txt
  A   grok/branches/darrylcousins-martian-layers/INSTALL.txt
  A   grok/branches/darrylcousins-martian-layers/LICENSE.txt
  A   grok/branches/darrylcousins-martian-layers/README.branch.txt
  A   grok/branches/darrylcousins-martian-layers/README.txt
  A   grok/branches/darrylcousins-martian-layers/TODO.txt
  A   grok/branches/darrylcousins-martian-layers/bootstrap/
  A   grok/branches/darrylcousins-martian-layers/bootstrap/bootstrap.py
  A   grok/branches/darrylcousins-martian-layers/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/buildout.cfg.orig
  A   grok/branches/darrylcousins-martian-layers/buildout.cfg1
  A   grok/branches/darrylcousins-martian-layers/doc/
  A   grok/branches/darrylcousins-martian-layers/doc/about.txt
  A   grok/branches/darrylcousins-martian-layers/doc/design/
  A   grok/branches/darrylcousins-martian-layers/doc/design/adapters.py
  A   grok/branches/darrylcousins-martian-layers/doc/design/annotations.py
  A   grok/branches/darrylcousins-martian-layers/doc/design/container.py
  A   grok/branches/darrylcousins-martian-layers/doc/design/grok_beginner.txt
  A   grok/branches/darrylcousins-martian-layers/doc/design/grok_dev.txt
  A   grok/branches/darrylcousins-martian-layers/doc/design/menu.py
  A   grok/branches/darrylcousins-martian-layers/doc/design/model.py
  A   grok/branches/darrylcousins-martian-layers/doc/design/permission.py
  A   grok/branches/darrylcousins-martian-layers/doc/design/skin-minimal.py
  A   grok/branches/darrylcousins-martian-layers/doc/design/skin.py
  A   grok/branches/darrylcousins-martian-layers/doc/design/subscriber.py
  A   grok/branches/darrylcousins-martian-layers/doc/design/traversal.py
  A   grok/branches/darrylcousins-martian-layers/doc/design/utility.py
  A   grok/branches/darrylcousins-martian-layers/doc/design/views.py
  A   grok/branches/darrylcousins-martian-layers/doc/grok2html.py
  A   grok/branches/darrylcousins-martian-layers/doc/grok2pdf.sh
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/INSTALL.txt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app_templates/anotherindex.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app_templates/sampleindex.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app_templates/bye.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/bootstrap.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/buildout_tut.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/containers/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/containers/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/containers/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app_templates/entryindex.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app_templates/sampleindex.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/empty/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/empty/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/empty/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app_templates/bye.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app_templates/edit.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app_templates/edit.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/static/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/static/style.css
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app_templates/edit.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app_templates/edit.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app_templates/edit.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app_templates/edit.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/setup.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/__init__.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/app.py
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/app_templates/
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/app_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/doc/index.txt
  A   grok/branches/darrylcousins-martian-layers/doc/naming_conventions.txt
  A   grok/branches/darrylcousins-martian-layers/doc/reference/
  A   grok/branches/darrylcousins-martian-layers/doc/reference/README.txt
  A   grok/branches/darrylcousins-martian-layers/doc/reference/components.tex
  A   grok/branches/darrylcousins-martian-layers/doc/reference/core.tex
  A   grok/branches/darrylcousins-martian-layers/doc/reference/decorators.tex
  A   grok/branches/darrylcousins-martian-layers/doc/reference/directives.tex
  A   grok/branches/darrylcousins-martian-layers/doc/reference/events.tex
  A   grok/branches/darrylcousins-martian-layers/doc/reference/exceptions.tex
  A   grok/branches/darrylcousins-martian-layers/doc/reference/functions.tex
  A   grok/branches/darrylcousins-martian-layers/doc/reference/model.tex
  A   grok/branches/darrylcousins-martian-layers/doc/reference/reference.tex
  A   grok/branches/darrylcousins-martian-layers/doc/release.txt
  A   grok/branches/darrylcousins-martian-layers/doc/style.tex
  A   grok/branches/darrylcousins-martian-layers/doc/template.pt
  A   grok/branches/darrylcousins-martian-layers/doc/tutorial.txt
  A   grok/branches/darrylcousins-martian-layers/doc/tutorial_outline.txt
  A   grok/branches/darrylcousins-martian-layers/ftesting.zcml
  A   grok/branches/darrylcousins-martian-layers/grokblog/
  A   grok/branches/darrylcousins-martian-layers/grokblog/README.txt
  A   grok/branches/darrylcousins-martian-layers/grokwiki/
  A   grok/branches/darrylcousins-martian-layers/grokwiki/README.txt
  A   grok/branches/darrylcousins-martian-layers/grokwiki/setup.py
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/__init__.py
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page.py
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/edit.pt
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/layout.pt
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/static/
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/static/wiki.css
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/wiki.py
  A   grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/xmlrpc.py
  A   grok/branches/darrylcousins-martian-layers/ldapaddressbook/
  A   grok/branches/darrylcousins-martian-layers/ldapaddressbook/README.txt
  A   grok/branches/darrylcousins-martian-layers/ldapaddressbook/setup.py
  A   grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/
  A   grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/
  A   grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/__init__.py
  A   grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/addressbook.py
  A   grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/martian/
  A   grok/branches/darrylcousins-martian-layers/martian/CREDITS.txt
  A   grok/branches/darrylcousins-martian-layers/martian/LICENSE.txt
  A   grok/branches/darrylcousins-martian-layers/martian/README.txt
  A   grok/branches/darrylcousins-martian-layers/martian/bootstrap.py
  A   grok/branches/darrylcousins-martian-layers/martian/buildout.cfg
  A   grok/branches/darrylcousins-martian-layers/martian/setup.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/README.txt
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/__init__.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/components.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/core.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/directive.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/directive.txt
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/error.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/interfaces.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/scan.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/scan.txt
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/__init__.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/__init__.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/classcontextbroken.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/classormodulecontext.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/modulecontext.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/onlyoncemodulecontext.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/__init__.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/cave.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/__init__.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/mammoth.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/mammoth_templates/
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/mammoth_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/notpackage/
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/notpackage/dummy.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/painting/
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/painting/__init__.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/test_all.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/__init__.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/alpha/
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/alpha/__init__.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/animal.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/beta/
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/beta/__init__.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/beta/three.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/one.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/two.py
  A   grok/branches/darrylcousins-martian-layers/martian/src/martian/util.py
  A   grok/branches/darrylcousins-martian-layers/setup.cfg
  A   grok/branches/darrylcousins-martian-layers/setup.py
  A   grok/branches/darrylcousins-martian-layers/setup.py.1
  A   grok/branches/darrylcousins-martian-layers/setup.py.orig
  A   grok/branches/darrylcousins-martian-layers/src/
  A   grok/branches/darrylcousins-martian-layers/src/grok/
  A   grok/branches/darrylcousins-martian-layers/src/grok/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/_grok.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/admin/
  A   grok/branches/darrylcousins-martian-layers/src/grok/admin/README.txt
  A   grok/branches/darrylcousins-martian-layers/src/grok/admin/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/admin/view.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/admin/view_templates/
  A   grok/branches/darrylcousins-martian-layers/src/grok/admin/view_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/components.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/configure.zcml
  A   grok/branches/darrylcousins-martian-layers/src/grok/directive.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/formlib.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/README.txt
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/admin/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/admin/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/admin/admin.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/catalog.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_app_interface.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_attribute.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_class.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_module.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_multiple.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_multiple_conflict.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_name.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_no_app.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_nonexistent.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_site.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/setuporder.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/actions.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform_applydata.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform_catalog.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata_classfields.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata_schema.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/form.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/templateform.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/update.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/grant.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/handle_exception.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/json.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/require.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/xmlrpc.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/ellie.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/file.txt
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/static.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/subdir/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/subdir/otherfile.txt
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/test_grok_functional.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/containertraverse.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/containertraverser.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/items_before_views.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/modeltraverse.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/traverser.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/application.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/redirect.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/url.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/url_function.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/local.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/local_override.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/multiple_class.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/multiple_directive.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/public.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/publicnoncontainer.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/subclass.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/argument.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/index.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/layer.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/macros.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/view.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc/
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc/xmlrpc.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc_helper.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/index.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/interfaces.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/meta.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/meta.zcml
  A   grok/branches/darrylcousins-martian-layers/src/grok/publication.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/templatereg.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/templates/
  A   grok/branches/darrylcousins-martian-layers/src/grok/templates/default_display_form.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/templates/default_edit_form.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/adapter.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/alphabetical.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontext.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextimported.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextmultiple.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextmultiple_fixture.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classorinterface.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/functioncontext.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsmany.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsnone.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsnonemulti.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/importedmodel.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/importedmodel2.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/interface.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/interfacemodule.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontext.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextimported.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextmultiple.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextmultiple_fixture.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiadapter.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiadaptsnone.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiple.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/namedadapter.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/nomodel.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/oldstyleclass.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/order.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/annotation.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/implementsmany.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/implementsnone.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/name.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/provides.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/application/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/application/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/application/application.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/base.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/basecontext.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/basedirective.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/container/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/container/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/container/container.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/container/container_model.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/argumenterror.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/argumenterror_fixture.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/multipletimes.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/error/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/error/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/error/error.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/event/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/event/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/event/errorconditions.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/event/errorconditions_fixture.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/event/subscriber.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/form/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/form/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/form/customautoform.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/form/customform.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/form/fields.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/form/form.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/form/norender.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/form/norender2.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/form/schemaform.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/form/schemainherit.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/continue_scanning.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/continue_scanning_fixture.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/grokcomponent.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/_meta.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/component.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/implementation.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/priority.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/priority_fixture.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/json/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/json/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/json/nocontext.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/json/view_lookup.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/security/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/security/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_json.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_json2.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc2.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc3.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require_json.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require_xmlrpc.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/security/view_decorator.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/site/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/site/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/site/site.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/static/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/static/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy_fixture/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy_fixture/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy_fixture/static/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy_fixture/static.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage_fixture/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage_fixture/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage_fixture/static/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage_fixture/static/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/test_grok.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/traversal/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/traversal/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/util/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/util/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/util/class_annotation.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsmany.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsmany2.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsnone.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsnone2.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsmany.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsnone.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsnone2.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/utility.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/ambiguouscontext.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirandinlinetemplate.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirandinlinetemplate_templates/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirandinlinetemplate_templates/cavepainting.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate_templates/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate_templates/cavepainting.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate_templates/food.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplateandrender.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplateandrender_templates/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplateandrender_templates/cavepainting.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly_templates/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly_templates/invalid.txt
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/eithertemplateorrender.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/explicitimplicittemplate.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inline.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inline_unassociated.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inlinebogus.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/missingcontext.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/namemultiple.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/namemultiple_fixture.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nameunicode.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nomodulename.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nomodulename_fixture.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/notemplateorrender.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/template.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatedirectory.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatedirectoryname/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatedirectoryname/food.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatefile.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatenotfound.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatereload.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatereload_templates/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatereload_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/twoviewsusetemplate.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/unassociated.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/unassociated_templates/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/unassociated_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/update.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/update_redirect.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/view/view.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/xmlrpc/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/xmlrpc/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/xmlrpc/nocontext.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveerror.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveimporterror.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveimporterror_fixture.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directivemodule.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directivepackage.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/cave.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/mammoth.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/mammoth_templates/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/mammoth_templates/index.pt
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/notpackage/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/notpackage/dummy.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/painting/
  A   grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/painting/__init__.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/util.py
  A   grok/branches/darrylcousins-martian-layers/src/grok/zcml.py

-=-
Added: grok/branches/darrylcousins-martian-layers/COPYRIGHT.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/COPYRIGHT.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/COPYRIGHT.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,10 @@
+Copyright (c) 2006 gocept gmbh & co. kg, Martijn Faassen and Philipp von
+Weitershausen
+All Rights Reserved.
+
+This software is subject to the provisions of the Zope Public License,
+Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+FOR A PARTICULAR PURPOSE. 


Property changes on: grok/branches/darrylcousins-martian-layers/COPYRIGHT.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/CREDITS.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/CREDITS.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/CREDITS.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,36 @@
+CREDITS
+=======
+
+* Martijn Faassen (original developer)
+
+* Wolfgang Schnerring (original developer)
+
+* Christian Theune (original developer)
+
+* Philipp von Weitershausen (original developer)
+
+* Jan-Wijbrand Kolman (Grok Zwei sprint, meta grokker improvements)
+
+* Darryl Cousins (website, admin interface)
+
+* Kevin Teague (website)
+
+* Tim Terlegård (JSON support)
+
+* Christian Zagrodnick (early grok discussions)
+
+* ME GROK (team mascot)
+
+Thank you
+---------
+
+* The Zope 3 developers, who provided the mountain for Grok to stand
+  on.
+
+* gocept for hosting the first grok sprint in Halle, Germany. Special
+  thanks to Felicia Faassen Wong, Christian Zagrodnick and Magda
+  Motyka for the delicious food.
+
+* Philipp von Weitershausen for hosting the second grok sprint in
+  Dresden, Germany. Special thanks to Heinrich von Jagwitz for the
+  delicious food.


Property changes on: grok/branches/darrylcousins-martian-layers/CREDITS.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/INSTALL.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/INSTALL.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/INSTALL.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,48 @@
+Preparing for grok development
+------------------------------
+
+Grok is installed via buildout <http://cheeseshop.python.org/pypi/zc.buildout>.
+
+You may have setuptools already installed for your system Python. In
+that case, you may need to upgrade it first because buildout requires
+a very recent version::
+
+    $ sudo easy_install -U setuptools
+
+If this command fails because easy_install is not available, there is
+a good chance you do not have setuptools available for your system
+Python. If so, there is no problem because setuptools will be
+installed locally by buildout.
+
+Bootstrap the buildout environment::
+
+    $ python bootstrap/bootstrap.py
+
+and run the buildout command::
+
+    $ bin/buildout
+    [lots of stuff will be downloaded and installed locally here]
+
+Running the demo applications
+-----------------------------
+
+Start the instance:
+
+    $ cd parts/instance
+    $ bin/zopectl fg
+
+If you now connect to port 8080 and log in with username 'grok',
+password 'grok', you should be able to add the grok-based applications
+(such as grokwiki) from the menu.
+
+Running the tests
+-----------------
+
+Grok's tests are easily run by executing the test runner that's
+installed in the ``bin`` directory::
+
+    $ bin/test
+
+For functional tests we've set up a special test instance just for
+running the test from, which includes the minimum needed ZCML (so the
+tests run a tidbit faster).


Property changes on: grok/branches/darrylcousins-martian-layers/INSTALL.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/LICENSE.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/LICENSE.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/LICENSE.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,54 @@
+Zope Public License (ZPL) Version 2.1
+-------------------------------------
+
+A copyright notice accompanies this license document that
+identifies the copyright holders.
+
+This license has been certified as open source. It has also
+been designated as GPL compatible by the Free Software
+Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the
+following conditions are met:
+
+1. Redistributions in source code must retain the
+   accompanying copyright notice, this list of conditions,
+   and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the accompanying
+   copyright notice, this list of conditions, and the
+   following disclaimer in the documentation and/or other
+   materials provided with the distribution.
+
+3. Names of the copyright holders must not be used to
+   endorse or promote products derived from this software
+   without prior written permission from the copyright
+   holders.
+
+4. The right to distribute this software or to use it for
+   any purpose does not give you the right to use
+   Servicemarks (sm) or Trademarks (tm) of the copyright
+   holders. Use of them is covered by separate agreement
+   with the copyright holders.
+
+5. If any files are modified, you must cause the modified
+   files to carry prominent notices stating that you changed
+   the files and the date of any change.
+
+Disclaimer
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS''
+  AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
+  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+  NO EVENT SHALL THE COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+  DAMAGE.


Property changes on: grok/branches/darrylcousins-martian-layers/LICENSE.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/README.branch.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/README.branch.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/README.branch.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,24 @@
+Grok-Martian-Layer Branch
+=========================
+
+* merged the mcweekly layer branch to the martian branch.
+* changed the buildout to use eggs
+* unit tests all pass
+* functional tests pass - cp ./ftesting.zcml to ./parts/test
+
+Bugs
+====
+
+* find out how to include ftesting file in parts/test with the buildout
+* in ftests/static/simple_fixture/ellie I needed to define grok.context on all
+  views
+
+
+To Do
+=====
+
+* start bringing z3c.form into the play
+
+Darryl Cousins
+darryl at darrylcousins.net.nz
+


Property changes on: grok/branches/darrylcousins-martian-layers/README.branch.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/README.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/README.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/README.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,40 @@
+What is grok?
+=============
+
+Grok makes it easier to get started with a Zope 3 web application.
+
+Grok uses the Component Architecture and builds on Zope 3 concepts
+like content objects (models), views, and adapters.  Its simplicity
+lies in using **convention over configuration** and **sensible
+defaults** when wiring components together.  That means neither a
+configuration language like ZCML nor a lot of repetition are needed to
+create a web application with grok.
+
+Who is grok?
+============
+
+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!"
+
+Getting grok
+============
+
+The easiest way to get started with grok is to install the
+`grokproject <http://cheeseshop.python.org/pypi/grokproject>`_ package
+(e.g. via ``easy_install grokproject``) and then create a new project
+area by calling the ``grokproject`` script like so::
+
+  $ grokproject MyProject
+  ... many lines of output here
+
+This will create a project area in ``MyProject`` as well as download
+and install grok and Zope 3 (the application server grok is built on).
+
+You can also get grok from the subversion repository::
+
+  svn co svn://svn.zope.org/repos/main/grok/trunk grok
+
+Then follow the instructions of ``INSTALL.txt``.


Property changes on: grok/branches/darrylcousins-martian-layers/README.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/TODO.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/TODO.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/TODO.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,117 @@
+====
+TODO
+====
+
+Meta
+====
+
+- Check demo applications for issues with patterns (grok wiki, ldap address
+  book)
+
+Core
+====
+
+- choice fields / sources (theuni)
+
+- testing strategy for the tutorial (faassen)
+
+- make it easier to write tests (wosc, faassen)
+
+- error reporting during grokking (provide file/line-number information
+  on our extrinsically generated errors) (philikon)
+
+- What will happen if we make a utility a old style class and use the
+  MRO stuff. Since we don't support non-persistent local utilities yet this
+  may be a rare case.
+
+- What about local utilities that don't subclass persistent? Perhaps we 
+  can look for IPersistent and give an error if the utility doesn't
+  state it is.
+
+- Change error messages: whenever we report about a callable, add
+  () to the name. Core Python expections do this.
+
+- JSON support similar to XMLRPC.
+
+Schema/formlib support
+----------------------
+
+- support nested class 'fields' directly on a view (do we really want this?)
+
+- list form for grok.Container (w/ zc.table?)
+
+- delete action on list form
+
+- make formlib macros available in some form?
+
+- what about subclassing a model that has a 'fields'?
+
+Need to discuss
+---------------
+
+- Do we want to ship Grok with a javascript library dependency such as
+  MochiKit, to enable out of-the-box AJAX?
+
+- Make it even easier to set up the catalog (intids should be set up
+  automatically if not already present. Perhaps Index grokkers?).
+
+- Testing support. Test grokkers?
+
+- Error pages: make it easy to register application-specific error
+  pages for exceptions.
+
+- Easier queries: integrate hurry.query in some way?
+
+- fall back to a static resource that is defined in a package on a higher
+  level if no static resource directory is defined locally in a package?
+
+- grok.grokkable (to allow grokking of imported things)
+
+- skins
+
+- form redirect
+
+- authentication (pau integration) (faassen)
+
+- sessions (get the session information for something, similar to
+  annotations?)
+
+- menus - define a menu, associate a view with a menu (module-level,
+  class-level)
+
+- making new widgets (faassen, philikon)
+
+- IMPORTANT: different strategies: grok.definefoo() versus n =
+  grok.Foo(), watch out for consistency/symmetry/...
+
+- use ZCML's conflict resolution machinery; actions for Grok.
+
+- do not accept automatic template directory guessing convention for
+  __init__.py, bail out with grok error instead?
+
+- grok.name, grok.template class restrictions (e.g. grok.template
+  should only be usable from grok.View subclasses)
+
+- support grok.template(template) in addition to
+  grok.template('name_of_template')?
+
+- support grok.resource on view class level?
+
+- should grok.context and grok.Model be order-dependent?
+  (so their meaning becomes "below here, this is the context")
+
+- Do we want to initialize model attributes for any schema that the model
+  implements (in addition to the initialization that is taking place for the
+  model-level fields)?
+
+Punt
+----
+
+- making new fields
+
+- viewlets / content providers (LATER)
+
+- RDB - via extension: megrok.sqlalchemy for example - make it easy to
+  go between the different schema implementations
+
+- containment constraints (wait for zope 3 to do them right)


Property changes on: grok/branches/darrylcousins-martian-layers/TODO.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/bootstrap/bootstrap.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/bootstrap/bootstrap.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/bootstrap/bootstrap.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,55 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id$
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+try:
+    import pkg_resources
+except ImportError:
+    ez = {}
+    exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                         ).read() in ez
+    ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)


Property changes on: grok/branches/darrylcousins-martian-layers/bootstrap/bootstrap.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,71 @@
+[buildout]
+develop = . grokwiki ldapaddressbook martian
+parts = grok test
+
+[zope3]
+location = .
+
+[grok-app]
+recipe = zc.zope3recipes:app
+site.zcml = <configure
+                xmlns="http://namespaces.zope.org/zope"
+                xmlns:browser="http://namespaces.zope.org/browser"
+                i18n_domain="zope">
+  <include package="zope.app.zcmlfiles" />
+  <include package="zope.contentprovider" />
+  <include package="zope.formlib" />
+  <include package="zope.i18n" file="meta.zcml" />
+  <include package="zope.i18n.locales" />
+  <include package="zope.security" file="meta.zcml" />
+  <include package="zope.traversing.browser" />
+  <include package="zope.app.securitypolicy" file="meta.zcml" />
+  <include package="zope.app.securitypolicy" file="configure.zcml" />
+  <include package="zope.app.authentication" />
+  <include package="zope.app.catalog" />
+  <include package="zope.app.intid" />
+  <include package="zope.app.keyreference" />
+  <include package="zope.app.twisted" />
+  <include package="zope.app.session" />
+  <include package="zope.viewlet" />
+  <!-- basic security setup to get me into grok admin -->
+  <securityPolicy component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
+  <role id="zope.Anonymous" title="Everybody" description="All users have this role implicitly" />
+  <role id="zope.Manager" title="Site Manager" />
+  <grant permission="zope.View" role="zope.Anonymous" />
+  <grant permission="zope.app.dublincore.view" role="zope.Anonymous" />
+  <grantAll role="zope.Manager" />
+  <unauthenticatedPrincipal id="zope.anybody" title="Unauthenticated User" />
+  <unauthenticatedGroup id="zope.Anybody" title="Unauthenticated Users" />
+  <authenticatedGroup id="zope.Authenticated" title="Authenticated Users" />
+  <everybodyGroup id="zope.Everybody" title="All Users" />
+  <!-- initial manager login and password -->
+  <principal id="zope.manager" title="Manager" login="grok" password="grok" />
+  <grant role="zope.Manager" principal="zope.manager" />
+  <!-- my friend the caveman -->
+  <include package="grok" file="meta.zcml" />
+  <include package="grok" file="configure.zcml" />
+  <include package="grokwiki" file="configure.zcml" />
+  </configure>
+
+eggs = grok
+       grokwiki
+       ldapaddressbook
+       martian
+
+[grok]
+recipe = zc.zope3recipes:instance
+application = grok-app
+zope.conf = ${database:zconfig}
+
+[database]
+recipe = zc.recipe.filestorage
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = grok
+       grokwiki
+       ldapaddressbook
+       martian
+defaults = ['--tests-pattern', '^f?tests$',
+            '-v'
+           ]

Added: grok/branches/darrylcousins-martian-layers/buildout.cfg.orig
===================================================================
--- grok/branches/darrylcousins-martian-layers/buildout.cfg.orig	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/buildout.cfg.orig	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,62 @@
+[buildout]
+develop = . grokwiki ldapaddressbook martian
+parts = data instance testdata testinstance test
+
+[zope3]
+#recipe = zc.recipe.zope3checkout
+#url = svn://svn.zope.org/repos/main/Zope3/branches/3.3
+location = /home/faassen/buildout/z331-lp
+
+[data]
+recipe = zc.recipe.filestorage
+
+[testdata]
+recipe = zc.recipe.filestorage
+
+[testinstance]
+recipe = zc.recipe.zope3instance
+database = testdata
+user = grok:grok
+eggs = setuptools
+       grok
+zcml = zope.annotation
+       zope.copypastemove
+       zope.formlib
+       zope.i18n-meta
+       zope.i18n.locales
+       zope.publisher
+       zope.security-meta
+       zope.size
+       zope.traversing
+       zope.traversing.browser
+       zope.app    
+       zope.app-meta
+       zope.app.securitypolicy
+       zope.app.securitypolicy-meta
+       zope.app.authentication
+       zope.app.catalog
+       zope.app.intid
+       zope.app.keyreference
+       grok
+       grok-meta
+
+[instance]
+recipe = zc.recipe.zope3instance
+database = data
+user = grok:grok
+eggs = setuptools
+       grok
+       grokwiki
+
+zcml = ${testinstance:zcml}
+       zope.app.twisted
+       grokwiki
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = grok
+extra-paths = /home/faassen/buildout/z331-lp/lib/python
+working-directory = parts/testinstance
+defaults = ['--tests-pattern', '^f?tests$',
+            '-v'
+           ]

Added: grok/branches/darrylcousins-martian-layers/buildout.cfg1
===================================================================
--- grok/branches/darrylcousins-martian-layers/buildout.cfg1	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/buildout.cfg1	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,94 @@
+[buildout]
+develop = . grokwiki ldapaddressbook martian
+parts = grok test
+
+[zope3]
+location = .
+
+[grok-app]
+recipe = zc.zope3recipes:app
+site.zcml = <configure
+                xmlns="http://namespaces.zope.org/zope"
+                xmlns:browser="http://namespaces.zope.org/browser"
+                i18n_domain="zope">
+            <include package="zope.app.component" file="meta.zcml" />
+            <include package="zope.app.component.browser" file="meta.zcml" />
+            <include package="zope.app.form.browser" file="meta.zcml" />
+            <include package="zope.app.pagetemplate" file="meta.zcml" />
+            <include package="zope.app.publication" file="meta.zcml" />
+            <include package="zope.app.publisher" file="meta.zcml" />
+            <include package="zope.app.security" file="meta.zcml" />
+            <include package="zope.app.securitypolicy" file="meta.zcml" />
+            <include package="zope.rdb" file="meta.zcml" />
+            <include package="zope.viewlet" file="meta.zcml" />
+            <include package="z3c.form" file="meta.zcml" />
+            <include package="z3c.macro" file="meta.zcml" />
+            <include package="z3c.pagelet" file="meta.zcml" />
+            <include package="z3c.template" file="meta.zcml" />
+            <include package="z3c.zrtresource" file="meta.zcml" />
+            <include package="zc.resourcelibrary" file="meta.zcml" />
+
+            <browser:menu id="zmi_views" title="Views" />
+            <browser:menu id="zmi_actions" title="Actions" />
+
+            <include package="zope.app.appsetup" />
+            <include package="zope.app.component" />
+            <include package="zope.app.container" />
+            <include package="zope.app.error" />
+            <include package="zope.app.i18n" />
+            <include package="zope.app.intid" />
+            <include package="zope.app.publication" />
+            <include package="zope.app.security" />
+            <include package="zope.app.securitypolicy" />
+            <include package="zope.app.session" />
+            <include package="zope.app.twisted" />
+            <include package="zope.app.wsgi" />
+            <include package="zope.annotation" />
+            <include package="zope.component" />
+            <include package="zope.contentprovider" />
+            <include package="zope.location" />
+            <include package="zope.publisher" />
+            <include package="zope.rdb" />
+            <include package="zope.traversing" />
+            <include package="zope.traversing.browser" />
+            <include package="zope.viewlet" />
+
+            <include package="z3c.form" />
+            <include package="z3c.formui" />
+            <include package="z3c.layer.pagelet" />
+            <include package="z3c.macro" />
+            <include package="z3c.pagelet" />
+
+            <include package="zc.resourcelibrary" />
+            <include package="zc.table" />
+
+            <include package="grok" file="meta.zcml" />
+            <include package="grok" file="configure.zcml" />
+
+            <!--browser:defaultView name="index.html" /-->
+            <!--browser:defaultSkin name="Z3CFormDemo" /-->
+
+            <securityPolicy
+            component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
+
+            <role id="zope.Anonymous" title="Everybody" />
+            <grantAll role="zope.Anonymous" />
+            </configure>
+eggs = grok
+       martian
+
+[grok]
+recipe = zc.zope3recipes:instance
+application = grok-app
+zope.conf = ${database:zconfig}
+
+[database]
+recipe = zc.recipe.filestorage
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = grok
+       martian
+defaults = ['--tests-pattern', '^f?tests$',
+            '-v'
+           ]

Added: grok/branches/darrylcousins-martian-layers/doc/about.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/about.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/about.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,137 @@
+======================================
+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 more easy to use and succinct.


Property changes on: grok/branches/darrylcousins-martian-layers/doc/about.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/doc/design/adapters.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/adapters.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/adapters.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,26 @@
+import grok
+from zope.publisher.interfaces.browser import IBrowserRequest, IBrowserView
+from zope.contentprovider.interfaces import IContentProvider
+from calc import Calculator
+
+class SingleAdapter(grok.Adapter):
+    grok.context(Calculator)
+    grok.adapts(Calculator)  # generally allowed, but not in this case, because there's already grok.context
+    grok.implements(ISomething)  # if this is not specified, app breaks
+    grok.provides(ISomething)  # if adapter implements more than one interface
+    grok.name('')  # this is actually the default
+
+    def something(self):
+        """self.context is automatically provided"""
+        return self.context.foo
+
+class CalculatorContentProvider(grok.MultiAdapter)
+    grok.adapts(Calculator, IBrowserRequest, IBrowserView)
+    grok.implements(IContentProvider)
+
+    def __init__(self, context, request, view):
+        self.context = context
+        self.request = request
+        self.view = view
+
+    # ...


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/adapters.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/design/annotations.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/annotations.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/annotations.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+import grok
+from zope import interface
+from BTrees.OOBTree import OOTreeSet
+
+class Article(grok.Model):
+    pass
+
+class IComments(interface.Interface):
+
+    def addComment(text):
+        pass
+
+    def getComments():
+        pass
+
+class Comments(grok.Annotation):
+    grok.context(Article)  # this is actually the default
+    grok.implements(IComments)
+    grok.name('annotations.Comments')  # this is actually the default
+
+    def __init__(self): 
+        self.comments = OOTreeSet()
+
+    def addComment(self, text):
+        self.comments.insert(text)
+
+    def getComments(self):
+        return list(self.comments)


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/annotations.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/design/container.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/container.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/container.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+import grok
+
+class Contact(grok.Model):
+    pass
+
+class AddressBook(grok.App, grok.Container):
+    pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/container.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/design/grok_beginner.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/grok_beginner.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/grok_beginner.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,412 @@
+==========================
+Grok: Making Zope 3 Easier
+==========================
+
+**NOTE:** This document was written *before* grok was implemented.  It
+has been part of the design phase during which it served well to
+discuss and preserve grok's goals.  The actual implementation of grok
+differs from the concrete code examples given here.  This is NOT a
+grok tutorial nor should it be seen as any part of grok's current
+documentation!
+
+
+Publishing web pages
+====================
+
+You want to publish a web site that is in a directory. This includes
+any pictures and javascript and CSS you may have in that directory::
+
+  import grok
+
+  class Website(grok.View):
+      grok.files('mydirectory')
+
+XXX use htdocs here, familiar to some people
+
+Once you do this, you can browse into these from the Zope 3 root site.
+Files and assets in any subdirectories will also be published. (XXX
+how?)
+
+Dynamic pages
+=============
+
+Often you want your web pages not to be static but *dynamic*. A web
+page is dynamic when, before the web page is served to your user for
+display in a browser, you want to generate part or all of the
+information of the web page automatically. 
+
+Zope reads your HTML files as Zope Page Templates (ZPT), meaning you
+can use TAL (Template Attribute Language) to script your
+templates. TAL is added to HTML as attributes, meaning your HTML still
+looks very familiar. For an example of very simple TAL, consider this
+HTML snippet::
+
+  <p tal:content="python:1 + 1">Result here</p>
+
+This will generate the following::
+
+  <p>2</p>
+
+This means that the result of the Python expression `1 + 1` is
+dynamically inserted as the content of this `p` tag, replacing what
+was already there.
+
+You can add TAL to any of your HTML pages to make them dynamic.
+
+For more about TAL see XXX (TAL tutorial in here?)
+
+Using Python
+============
+
+Just TAL by itself, even when you use `python:` to embed snippets of
+Python, is limited. The idea of good application design is to use TAL
+just for fairly simple templating purposes, and to do anything a bit
+more complicated in Python code. Using TAL with Python code is easy:
+you just add methods to your view class and use them from your
+template. 
+
+Here we add a method that formats the current date and time::
+
+  from zope import grok
+  from datetime import datetime
+
+  class Website(grok.View):
+      grok.files('mydirectory')
+      
+      def currentDatetime(self):
+          return datetime.now().strftime('%Y-%m-%d %H:%M')
+
+We can then use this with TAL to display the current date and time::
+
+  <p tal:content="view/currentDatetime">Datetime goes here</p>
+
+All the methods you add to the class of your site are automatically
+available on the special `view` name from within your
+templates. `view` is one of the few names that are available in views
+by default.
+
+Note that we have used TAL's built-in `path` language here; this can
+be used for simple method calls instead of spelling it out explicitly.
+For the same effect, you can also use it using Python directly::
+
+  <p tal:content="python:view.currentDatetime()">Datetime goes here</p>
+
+This can be useful when you want to pass parameters to your methods.
+
+Generating HTML from Python
+===========================
+
+Sometimes you want to generate complicated HTML in Python and then
+include it in an existing web page. For reasons of security against
+cross-site scripting attacks, TAL will automatically escape any HTML
+into `&gt;` and `&lt;`. With the `structure` directive, you can tell
+TAL explicitly to not escape HTML this way, so it is passed literally
+into the template::
+
+  from zope import grok
+
+  class Website(grok.View):
+      grok.files('mydirectory')
+    
+      def someHTML(self):
+           return '<strong>%s</strong>' % (1 + 1)
+
+And then with TAL in one of your templates::
+
+  <p tal:content="structure view/someHTML">Result goes here</p>
+
+Generating the whole page from Python
+=====================================
+
+If for some reason you do not want to use a HTML template but just
+want to generate HTML directly from Python, this is also possible::
+
+  class Foo(grok.View):
+      @grok.page('serverload.html')
+      def serverLoad(self):
+          return '<html>..</html>'
+
+XXX a word on unicode
+
+Simple forms
+============
+
+Typical web applications have forms. Let's make a web form and use
+it. First we'll add the following form to one of our templates::
+
+  <form action="hello.html" method="post">
+    <p>
+    Please type your name: <input type="text" name="name" value="" /><br/>
+    <input type="submit" value="Submit" />
+    </p>
+  </form>
+
+As you can see, this form submits to the template named
+`hello.html`. Create such a template in your site and put the
+following TAL in there::
+
+  <html><body>
+  <p>Hello, <strong tal:content="request/form/name">name</strong></p>
+  </body></html>
+
+Now when you go to the form and submit it with the name `John`, you
+should see a web page that says:
+
+  Hello **John**
+
+Simple forms with Python
+========================
+
+Let's make a simple calculator to demonstrate how we combine this with
+Python::
+
+  <form action="sum.html" method="post">
+    <p>
+    First value: <input type="text" name="first" value="" /><br />
+    Second value: <input type="text" name="second" value="" /><br />
+    <input type="submit" value="Get the sum" />
+    </p>
+  </form>
+
+And create the following template `sum.html`::
+
+  <html><body>
+  <p>The sum is: <strong tal:content="data/sum">the sum goes here</strong></p>
+  </body></html>
+
+We've referred to a method `sum` here that does not exist yet, so let's
+implement it. It takes the raw values in the request and adds them to
+together, returning the sum::
+
+  from zope import grok
+
+  from ... import TemplateFile
+
+  class Website(grok.View):
+      grok.files('mydirectory')
+
+      @grok.page('sum.html')
+      def sum(self):
+          # before
+          self.sendEmail()
+          # call template (pull calculateSum2)
+          result = self.renderTemplate('sum.html', sum=self.calculateSum())
+          # post processing
+          result = result.replace('foo', 'bar')
+          return result
+
+
+      def sum(self):
+          self.before()
+          result = self.render('sum.html', **self.push())
+          result = self.after(result)
+          return result
+
+      def before(self):
+          pass
+
+class Website(grok.View):
+      grok.files('mydirectory')
+  
+      class sum(object):
+          """corresponds to sum.html"""
+ 
+          @grok.before()
+          def sendEmail(self):
+            ...
+
+          @grok.after()
+          def barify(self, result):
+              return result.replace('foo', 'bar')
+
+          def calculateSum(self):
+              return ...
+
+          def sum2(self):
+              return ...
+
+      class fancysum(sum):
+          """corresponds to fancysum.html"""
+
+           def calculateSum(self):
+                ...
+
+     
+      @grok.data('sum.html', 'sum')      
+      def sum(self):
+          # get hold of the form, from the request object that
+          # we can get from self
+          form = self.request.form
+          # now get first and second from the form; if no value found
+          # assume it's 0
+          first = form.get('first', 0)
+          second = form.get('second', 0)
+          # convert the input which was text to the numbers
+          # note that we don't handle any errors yet in case someone fills in
+          # something that's not a number
+          first = int(first)
+          second = int(second)
+          # now add the numbers and return this result
+          return first + second
+
+      @grok.page('sum.html')
+      def sum(self):
+          return "<html>...</html>"
+
+
+Form side effects
+=================
+
+Often you don't just want to see a result page when a user submits a
+form, but you want the let the system do some work just before we show
+the result. An example of this is to send an email. Another common
+example is to store the data that's in the form in a database
+somewhere. 
+
+This can be easily accomplished using the `@grok.before` decorator,
+which allows us to execute some Python code just before the template
+is rendered::
+
+  class Website(grok.View):
+      grok.templates('mydirectory')
+    
+      @grok.before('email_sent.html')
+      def email(self):
+          ... send the email XXX ... 
+
+
+Storing data
+============
+
+Instead of emailing the data, what if we wanted to record what the
+user entered instead? Zope offers a number of options for storing
+data, such as making a connection to relational databases (XXX which
+we'll handle later?), but Zope also ships with a powerful database of
+its own: the Zope Object Database (ZODB).
+
+The ZODB is a database of Python objects. You can store any Python object
+in it, and there are just a few things you need to be aware of initially:
+
+* You should subclass your own data classes from persistent.Persistent
+  so it's easy to store them in the ZODB.
+
+* To make sure the ZODB knows you changed a mutable attribute in the
+  instance, set the special `_p_changed` attribute on that instance to
+  `True`. This is only necessary if that attribute is not `Persistent`
+  itself. It's not necessary when you assign to an attribute directly
+  using `=`.
+
+This may sound complicated but it's not. Don't worry for now - most
+things work as normal in Python, and the rules just described are not
+difficult.
+
+So how do we get a space in the database to store our data in?
+`zope.grok` supports a special area where you can store your data.
+
+To get to the database in Python code, call `grok.database()`. This
+gives us access to a dictionary-like object, in which we can store our
+own sub objects::
+
+  from zope import grok
+  from persistent import Persistent
+
+  class NamesStorage(Persistent):
+     def __init__(self):
+        self.names = []
+
+    def addName(self, name):
+        self.names.append(name)
+        self._p_changed = True
+
+  class Website(grok.View):
+     grok.templates('mydirectory')
+   
+     def getNamesStorage(self):
+         """Get the names storage, or create it if it's not there yet.
+         """
+         db = grok.database()
+         storage = db.get('myapp.names_storage')
+         if storage is None:
+             db['myapp.names_storage'] = NamesStorage()
+         return storage
+
+     def storeName(self):
+         """
+         Retrieve the name from request and store it in
+         the names section.
+         """
+         storage = self.getNamesStorage()
+         storage.addName(self.request['name'])
+         
+XXX should following be separate section?
+
+Note that storing names in a list is not very efficient if the list of
+names grows to a larger size, as the object database will need to load
+the whole list of names into memory each time it is changed. We can
+avoid this using BTrees. XXX BTree explanation
+
+XXX showing the names in a web page
+
+Self-posting forms 
+==================
+
+It's a good design for many forms to be *self-posting*, that is, the
+result of a form submission shows the original form again. This way,
+mistakes by the user can be easily shown in the context of the form,
+and the user can correct them. When the form submission does succeed,
+the user is commonly redirected to another page.
+
+Let's first make a form that posts to itself, we'll call it just
+`form.html`::
+
+  <html><body>
+    <form action="." method="post">
+      <input type="text" name="number" value="" />
+    </form>
+  </body></html>
+
+We expect the user to enter an integer number, and we also want it the
+number to be required. Only if those conditions are true 
+....
+
+XXX can't use . perhaps, need to do absolute trick and explain it: request/URL
+
+n. .. self posting form ..
+
+Powerful forms using formlib
+============================
+
+class Foo(grok.View):
+
+    class Form(grok.Form):
+       grok.name('entry.html')
+       # would really be step 7 to control the template
+       # that renders the form. (this template needs to be
+       # moved)
+       template = grok.Template('entry.html')
+       
+       form_fields = grok.Fields(
+          name=schema.TextLine(title='Name'),
+          )
+
+       @grok.action('Submit')
+       def handle_submit(self, action, data):
+           .. send email ..
+           self.message = "The mail has successfully been sent."
+
+
+
+class MeetingView(grok.view):
+
+    grok.context(IMeeting, id=getfromrequestpath)
+
+n. You want to associate your application to a specific site
+
+n. You want to create a site content object
+
+n. You want to create a content object and associate views to that.
+
+n. You want to index content objects to search them.
+
+
+Some basic explanation of what's going on with unicode in Zope 3.


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/grok_beginner.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/doc/design/grok_dev.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/grok_dev.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/grok_dev.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,394 @@
+==========================
+Grok: Making Zope 3 Easier
+==========================
+
+**NOTE:** This document was written *before* grok was implemented.  It
+has been part of the design phase during which it served well to
+discuss and preserve grok's goals.  The actual implementation of grok
+differs from the concrete code examples given here.  This is NOT a
+grok tutorial nor should it be seen as any part of grok's current
+documentation!
+
+Introduction
+============
+
+The Grok project tries to it easier to develop Zope 3
+applications. Zope 3 is typically configured using ZCML, the Zope
+Configuration Markup Language. ZCML is non-Python and very explicit.
+
+ZCML was in part inspired by the difficulties surrounding
+configuration in Zope 2. Zope 2 is heavy on implicit configuration
+("no docstring means no public access", "a permission used is a
+permission defined"). In addition, lots of the configuration happens
+in Python code, such as in the `__init__.py` of a product. These
+techniques can lead to problems: hard to understand configuration code
+interweaved with non-configuration code. Such code tends to be
+difficult to maintain, extend, and evolve.
+
+ZCML aims to separate configuration strongly from software to avoid
+these problems. The ZCML model in combination with the notion of
+explicit interfaces offers a strong model for evolving software over a
+longer period of time.
+
+ZCML has drawbacks however. Zope 3's setup for modularity, components
+and evolution results in more entities for a programmer to worry
+about: explicit interfaces, a multiplication of files and modules, a
+large list of places to import from, a series of ZCML directives to
+remember. Even though individual entities may be easier to understand,
+the combination of such can make the whole more difficult to
+understand, and there is just a lot to learn overall.
+
+This is especially off-putting to developers who are trying to start
+learning Zope 3. Even experienced programmers can be frustrated by so
+much need to state obvious things explicitly - the multiplication of
+entities in Zope 3 hurts agility of development. Finally, ZCML can be
+intimidating to a Python programmer merely by being non-Python, and
+XML in particular. While the latter is at least in part a superficial
+concern, it is one that stops people from trying Zope 3.
+
+Grok aims to reduce the visibility of ZCML to the Zope 3
+programmer. Grok also aims to reduce the entities a programmer needs
+to worry about: ideally a Zope 3 application should be able to fit
+completely inside a single module. Grok does not aim to do away with
+ZCML altogether: explicit configuration is valuable. Grok merely aims
+to keep the advanced concepts out of the programmer's face when not
+needed.
+
+How does Grok aim accomplish these goals? We will try to follow the
+guidelines that work for Ruby on Rails:
+
+* DRY: Don't Repeat Yourself
+
+* Convention over configuration
+
+Grok is specified as autogenerated ZCML. This is for convenience of
+specification: Grok does not need to be implemented this way but could
+be calling underlying component architecture APIs directly where
+needed. In fact, one of the aims of Grok is to produce more readable
+errors that guide programmers into the right direction to solve their
+problem.
+
+Grok does not aim to make the programmer do correct security - an
+application written with Grok without the programmer taking any
+particular actions will be entirely public by default. Convenience of
+development trumps security here. The idea of Grok is that the
+programmer should have the easiest time possible to get an application
+running first, and then can gradually tighten the application in
+various ways, including security, later on.
+
+Views
+-----
+
+To declare a browser view, a new class-level declaration `views` is
+added, with as argument the class or interface the view is being
+declared for::
+
+  from zope import grok
+
+  class FooView(grok.View):
+     grok.views(Foo)
+
+As you can see, Grok views are inherited from `grok.View`.
+
+This is equivalent to the following ZCML::
+
+  <browser:page
+    name="FooView"
+    for="Foo"
+    class="FooView" 
+    permission="zope.Public"
+    />
+
+Note that the name is deduced entirely from the name of the view
+class. Where this is not desired, the view name can be controlled
+using the `name` declaration on the view:
+
+  from zope import grok
+
+  class FooView(grok.View):
+      grok.name("info.html")
+      grok.views(Foo)
+
+      @grok.page('info.info')
+      ...
+
+which translates to::
+
+  <browser:page
+     name="info.html"
+     for="Foo"
+     class="FooView"
+     permission="zope.Public"
+   />
+
+It's also possible to set the skin the view is in using ``skin``
+declaration::
+
+  from zope import grok
+  from myskin import IMySkin
+
+  class FooView(grok.View):
+     grok.skin(IMySkin)
+
+XXX can we somehow stop the concept of interface from being introduced
+here? Class-based skins?
+
+Views that do not specify *any* declarations but inherit from
+grok.View are also automatically registered, for everything (`*`)::
+
+  from zope import grok
+
+  class MyView(grok.View):
+     def getData(self):
+         return fadfkjdlkfjd
+     __call__ = template('foo.pt')
+
+is equivalent to the following ZCML::
+
+  <browser:page
+     name="MyView"
+     for="*"
+     class="MyView"
+     permission="zope.Public"
+     />
+
+View Security 
+-------------
+
+The default permission on views generated by Grok is `zope.Public`. At
+first glance, this seems to be going back to the bad old insecure days
+of Zope 2. Zope 3 has a different security model though: content
+objects can declare their own security. Since Grok declares content
+objects entirely public by default as well however, that is not a very
+strong argument.
+
+The more important argument for this "wide-open" default is that
+dealing with security issues early on in application development tends
+to be very painful and distracting for most application developers,
+breaking their flow. The temptation is therefore large to just give
+any permissions that will permit the developer to continue. Security
+issues are typically ignored until a later stage of development. We
+recognize this pattern of development, and we can't really enforce
+developers doing security right anyway, so Grok doesn't aim to try.
+
+Of course it is possible to override the default, using a class
+declaration on the view called `permission`::
+
+  from zope import grok
+
+  class MyView:
+     grok.views(SomeContent)
+     grok.permission('zope.ManageContent')
+
+Non-existing permissions are not created automatically - new
+permissions have to be declared explicitly, using ZCML.
+
+Finally, Grok also offers a "security testing" mode, where the default
+permission of all views in a package is specified by the
+developer. This can be used at a later stage during development to
+flush out any security problems.
+
+XXX explain spelling for that
+
+Class security
+--------------
+
+Attributes, both reading and writing on content are protected with the
+`zope.Public` permission by default. The aim of Grok is to get out of
+the programmers hair.
+
+How does Grok determine that something is a content class and thus
+should have its attributes made public?
+
+Grok determines something is a content class if:
+
+* it has views that directly view it
+
+* it is a subclass of a class that has views
+
+* it has an interface that has views registered for it
+
+For the purposes of security, views registered for `*` do *not* count
+as views registered for a class or interface.
+
+To restrict the permission of a content class explicitly, the same
+`permission` class declaration can be used as the one defined for
+views. This declaration sets the default access permission for *all*
+attributes of the class::
+
+  from zope import grok
+
+  class FooContent:
+     grok.permission('zope.ManageContent')
+
+It is often desirable to make an exception for some attributes, however::
+
+  from zope ipmort grok
+
+  class FooContent:
+     grok.permission('myapp.View')
+
+     @@grok.protected('myapp.Edit')
+     def protectedMethod(self):
+         pass
+
+     @@grok.private()
+     def privateMethod(self):
+         pass
+
+     def _alsoPrivate():
+         pass
+
+As soon as specific declarations are used to restrict the access to
+various methods, the default view permission of `zope.Public` does not
+apply anymore for that class.
+
+Importing 
+---------
+
+As you've seen from the examples, every import in a simple Grok
+application will be from the `zope.grok` package. This means that the
+developer does not need to remember a complicated set of imports from
+a wide-ranging set of packages just to build a simple package.
+
+This is the opposite of the current trend in Zope 3 development:
+imports from `zope.app.zapi`, intended to be an easy location to get
+important stuff are replaced with the imports from the real location.
+
+`zope.app.zapi` as an approach to simplify things failed for a number
+of reasons: it not very coherent, so hard to predict what ended up
+there, and it was incomplete: to build a real Zope 3 application you
+always needed to import from places beyond `zope.app.zapi`. In
+contrast, `zope.grok` aims to provide a relatively small number of
+names to use, and that should be *all* needed to produce a simple
+`zope.grok`-based application.
+
+Of course as a grok-based application grows developers will find
+themselves importing from other package. This should be a voyage of
+gradual discovery for the developer. There should be no need to go the
+whole way right away.
+
+XXX possible exceptions: zope.schema, zope.formlib
+
+Schema-classes
+--------------
+
+It is possible to define the schema of a class directly::
+
+  from zope import grok
+
+  class MyContent(grok.Content):
+     class data:
+         foo = TextLine(u'Foo')
+
+Fields defined are automatically created as attributes on instances
+using the defaults specified by the fields (the default default if no
+default is specified).
+
+XXX schema really should accept pure ascii strings in all cases
+    instead of unicode strings, and not *require* a u'' in front of
+    strings and give an obscure error. If you need non-ascii, *then*
+    you worry about unicode. Yet another thing less to explain to
+    beginners however.
+
+XXX we cannot use the name `schema` for the schema inner class as that
+    would conflict with `from zope import schema`...
+
+By default the schema is readable and writeable by all.
+
+The schema read and write permissions for schema fields can be set
+using special class declarations::
+
+  from zope import grok
+
+  class MyContent(grok.Content):
+     class data:
+        read_permission('myapp.View')
+        write_permission('myapp.Edit')
+
+        foo = TextLine(u'Foo')
+
+XXX want to handle the usecase of a class with multiple related
+    schemas that have an inheritance relationship to each other?
+
+No interfaces necessary
+-----------------------
+
+A Grok application can be written without a single interface in
+sight. No interfaces means less entities for the developer to care
+about, and the goal of grok is to avoid having to worry about
+interfaces when building an application. Interfaces can always be
+added later during the evolution of an application.
+
+XXX exception for skins at present..
+
+As an application grows a developer can start introducing interfaces:
+grok does not *stop* the use of interfaces.
+
+Adapters
+--------
+
+XXX is this something to be treated by grok or is this an "advanced
+topic" outside the purview of grok? It should be easy to recognize
+adapters that use `adapts()` and automatically register them.
+
+Forms
+-----
+
+Let's see how `zope.formlib` fits in with grok::
+
+  from zope import schema
+  from zope import grok
+
+  class MyContent(grok.Content):
+     class data:
+         name = schema.TextLine("Name")
+         age = schema.Int("Age")
+
+  class MyContentView(grok.EditForm):
+     grok.name('edit.html')
+     grok.views(MyContent)
+
+     # XXX can it be automatically deduced where the fields come from
+     # at this point?
+     form_fields = grok.Fields()
+
+     grok.action('Ok')
+     def handle_input(self, action, data):
+        pass
+
+XXX should be really be covering up formlib.form? ``grok.Fields()``
+    seems to imply we might have to.
+
+Templates
+---------
+
+This sets up a template to use::
+
+  from zope import grok
+
+  class MyView(grok.View):
+     grok.template('mytemplate.pt')
+
+XXX Sensible default behavior:
+
+  * use template for __call__ if no __call__ defined
+
+  * template/update pattern?
+
+Menus
+-----
+
+XXX How to make things show up in menus? When we create a new content
+object we at least want an easy way to create it, though not
+necessarily through the ZMI. Menu class declaration?
+
+TDB
+---
+
+* Easy way to generate add views
+
+* easy local utility registration?
+
+* bread - easy creation of tables, catalog-based search
+


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/grok_dev.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/doc/design/menu.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/menu.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/menu.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,192 @@
+"""megrok.menu
+
+A simple but extensible menu system for Zope 3.
+
+What is a menu?
+
+    For web applications there are two competing design patterns that can be
+    handled under the term 'menu': classic GUI menus and web site navigation.
+
+    The essential difference in those two is the 'status' or 'context' of the
+    menu. In classic GUI applications, a menu is (more or less) stateless,
+    independent of the view to the application that is currently being used.
+
+    In classic web sites, the navigation gives a navigatable overview of the
+    site's hierarchy using an 'active' flag to indicate the user's position in
+    the site.
+
+    In web applications those two concepts start to mix.
+
+    The basic implementation of the menu system takes care of the classic
+    listing of options a user has in a specific context.
+
+    An extension mechanism is used to provide status-annotation to menu items
+    to show where a user currently is.
+
+Design goals:
+
+    -   Simple, central, menu definition without ZCML
+
+    -   Allow submenus.
+
+    -   Make status determination pluggable to allow for application-specific
+        complex scenarios without tainting the menu system.
+
+Menu rendering process:
+
+    -   create set of choices (apply filters in context, permissions, condition)
+
+    -   apply (status) annotations
+
+Determining whether an item is active:
+
+    a) Model based
+
+    - find out which object belongs to the menu item
+
+    - Is this object the same as the context of the menu?
+
+    b) View based
+
+    - find out which view belongs to the menu item
+
+    - Is it the currently published view?
+
+    Generalisation: 
+
+Zope/Grok stuff:
+
+    -   Menus are utilities
+
+Questions:
+
+    -   How to integrate with skin layers?  
+
+    -   Aren't menus just browser views? (context, request)
+
+    -   Two variations: allow menu items to render their HTML, or not? 
+
+        Allow HTML:
+
+            - provides ability to implement various menu item types
+
+            - codes in presentation
+
+        Don't allow HTML:
+
+            - more flexible to customize?
+
+        -> use views on menu items!
+"""
+
+import grok
+from megrok import menu
+
+class AddressBook(grok.Model):
+    pass
+
+class Contact(grok.Model):
+    pass
+
+class EditContact(grok.EditForm):
+    grok.context(Contact)
+    grok.annotation("title", _(u"Edit XY"))
+
+
+layout = grok.PageTemplate("""\
+<html>
+<body>
+
+    <!-- Most simple: Render the whole menu -->
+    <div tal:replace="structure menu/main/@@links"/>
+
+    <!-- Variation 1: Render whole menu as drop down list -->
+    <div tal:replace="structure menu/main/@@dropdown"/>
+
+    <!-- Variation 2: Render menu manually, get each item as link
+    <ul>
+        <li tal:repeat="item menu/main">
+            <a tal:replace="structure item/@@link">
+        </li>
+    </ul>
+
+    <!-- Variation 3: Render menu and items manually 
+    <ul tal:repeat="item menu/main"><a tal:attributes="href item/action" tal:content="item/title"></ul>
+    </ul>
+
+    <!-- Variation 4: Render option elements automatically -->
+    <select>
+        <option tal:repeat="item menu:main" tal:replace="item/@@option">
+    </select>
+
+    <!-- Bind the menu to a different object explicitly -->
+    <div tal:replace="structure python:menu['main'].bind(object1, request)"/>
+    '
+    <!-- Alternative: use a grok variable in the templates: -->
+    <div tal:replace="structure grok/menu/main/context:asdf/"/>
+
+
+
+    <grok:menu 
+</body>
+</html>""")
+
+class IMenuItem(Interface):
+
+    action
+    title
+    submenu
+
+
+main = menu.Menu(
+    menu.View(EditContact),         # Link to a view. Necessary information: context, name
+                                    # Link to a generic action/URL
+    menu.Action(_("External action"), "string:http://${context/"),
+    menu.SubMenu(
+        menu.Item(
+
+
+############ Implementation sketches
+
+class ViewMenuItem(object):
+
+    def __init__(self, view):
+        # View must be a view
+        
+
+class Action(object):
+    
+    def __init__(self, title, target):
+        self.title = title
+        self.target = target    # TALES expression
+
+    def 
+
+
+class BaseMenuItem(object):
+
+    def __init__(self, condition):
+        self.condition = condition
+
+    def checkCondition(context, request):
+        # - does this item apply in the given context?
+        # - does the user have the necessary permissions
+        # - does the user supplied condition evalute to true? 
+    
+
+class Menu(object):
+
+    def __init__(self, menu_items):
+        # XXX assert: All items must be menu items
+        self.menu_items = menu_items
+
+    def __call__(self, context, request):
+        relevant_items = []
+
+        for item in self.menu_items:
+            if not item.checkCondition(context, request):
+                continue
+
+            relevant_item.append(item)
+
+


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/menu.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/design/model.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/model.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/model.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,56 @@
+"""
+Schema-driven development with grok
+"""
+import grok
+
+grok.directory('contact')
+
+class Contact(grok.SchemaModel):
+    """
+    This works now:
+
+      >>> c = Contact(name=u'Martijn', city=u'Rotterdam')
+      >>> c.name
+      u'Martijn'
+
+    Also w/o kw:
+
+      >>> c = Contact(u'Martijn', u'Rotterdam')
+      >>> c.name
+      u'Martijn'
+
+    """
+    class fields:
+        name = schema.TextLine()
+        city = schema.TextLine()
+
+
+class Edit(grok.EditForm):
+    pass
+    # this will automatically render an edit form, and use an
+    # 'edit.html' template if available
+
+class Index(grok.DisplayForm):
+    pass
+    # this will automatically render an display form, and use an
+    # 'index.html' template if available
+
+class Add(grok.AddForm):
+    grok.context(Contact)  # this is actually the default
+    grok.container(IContainer)  # this is actually the default
+
+class FancyEdit(grok.EditForm):
+    """ use cases:
+
+    * (actions with permissions)
+
+    *
+
+    """
+
+    @grok.action("Save")
+    def save(self, **data):
+        """
+        this overrides any actions defined on the base class
+        """
+        self.applyChanges(data)


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/model.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/design/permission.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/permission.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/permission.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,36 @@
+import grok
+
+grok.definepermission('grok.Complex')  # define permission first
+
+class Complex(grok.Model):
+    # this sets the default for all methods
+    grok.require('zope.Public')  # this is actually the default
+
+    # this sets the default for reading all attributes that are not methods
+    grok.readable('zope.Public')  # this is actually the default
+
+    # this sets the default for writing all attributes that are not methods
+    grok.writable('zope.Public')  # this is actually the default
+
+    # this overrides the above
+    grok.readable('grok.Complex', 'attr1') # override default
+    grok.readable('zope.ManageServices', 'attr2') # override default
+    grok.writable('zope.ManageContent', 'attr1', 'attr2') # override default
+
+    def __init__(self):
+        self.attr1 = 1
+        self.attr2 = 2
+
+    @grok.require('some.permission')
+    def doSomethingVerySecret(self):
+        pass
+
+    @grok.require('zope.Public')  # this is actually the default
+    def imPublic(self):
+        pass
+
+class SubClass(Complex):
+    # it's all inherited
+
+    grok.readable('zope.Public', 'attr1')
+


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/permission.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/design/skin-minimal.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/skin-minimal.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/skin-minimal.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,18 @@
+import grok
+from zope import interface
+
+
+grok.definelayer('my')
+grok.defineskin('my')                 # Picks up the layer 'my' if it exists
+
+grok.layer('my')                      # If there is only a single layer defined
+                                      # in a module, it will be the default
+
+
+class Painting(grok.View):
+    pass
+
+
+fireplace = grok.PageTemplate("""\
+<html><body></body></html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/skin-minimal.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/design/skin.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/skin.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/skin.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,25 @@
+import grok
+from zope import interface
+
+
+grok.definelayer('my')
+grok.definelayer('admin')
+
+grok.layer('my')
+
+grok.defineskin('my', ['my'])         # this is the default
+grok.defineskin('my')                 # does the same as the line above
+grok.defineskin('admin', ['admin', 'my'])
+
+
+class Painting(grok.View):
+    pass
+
+
+fireplace = grok.PageTemplate("""\
+<html><body></body></html>
+""")
+
+
+class AdminPainting(grok.View):
+    grok.layer('adminlayer')


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/skin.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/design/subscriber.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/subscriber.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/subscriber.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,11 @@
+from zope.lifecycleevent.interfaces import IObjectModifiedEvent
+from calc import Calculator
+import grok
+
+ at grok.subscriber(Calculator, IObjectModifiedEvent)
+def calculatorChanged(calc, event):
+    pass
+
+
+# perhaps alias zope.event.notify to grok.notify???
+


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/subscriber.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/design/traversal.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/traversal.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/traversal.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,50 @@
+import grok
+
+class Appointment(grok.Model):
+    pass
+
+class Day(grok.Model):
+
+    def getAppointment(self, number):
+        if number in self.appointments:
+            return Appointment(number)
+        return None # try to look up views then
+
+    def traverse(self, name):
+        return self.getAppointment(int(number))
+    
+class Calendar(grok.Model):
+    def getYear(self, year):
+        return Year(year)
+
+    def traverse(self, name):
+        return self.getYear(int(number))
+
+# interpretation of traverse:
+
+# * do the traverse traversal first
+
+# * if this raises an error, propagate exception, do not swallow it (test)
+
+# * if this returns None, fall back on "normal" traversal for the
+    object (i.e. container traversal)
+
+"""
+http://.../calendar/2006/10/13/1/
+           ^^^^^^^^ ^^^^ ^^ ^^ ^
+            Cal.    Year  ...  A.
+"""
+
+#XXX routes (http://routes.groovie.org/) for advanced cases
+
+
+# instead of traverser on the model, you can also write a separate
+# traverser component:
+
+class CalendarTraverser(grok.Traverser):
+    grok.context(Calendar)  # this is actually the default
+    grok.register(site=CalendarApp)  #...
+
+    def traverse(self, name):
+        now look up stuff on self.context with 'name'...
+        return that


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/traversal.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/design/utility.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/utility.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/utility.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,31 @@
+import grok
+
+class Calculator(grok.GlobalUtility):
+    grok.implements(ICalculator)  # if this is not specified, it breaks
+    grok.name('')  # this is actually the default
+    grok.provides(ICalculator) # this is actually the default
+
+grok.global_utility(factory, provides=IFace, name=u'')
+
+class Calculator(grok.LocalUtility):
+    grok.utility_provides(ICalculator)
+
+class Anything(grok.Model):
+    pass
+
+class NonPersistent(object):
+    pass
+
+class SpecialAnything(Anything):
+    pass
+
+class Foo(grok.Model, grok.Site):    
+    grok.local_utility(Anything, hide=False, name_in_container='foo',
+                       persistent=None)
+    grok.local_adapter()
+    grok.local_view()
+
+class Foo2(Foo):
+    grok.local_utility(SpecialAnything)
+
+    


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/utility.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/design/views.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/design/views.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/design/views.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,85 @@
+import grok
+
+grok.templatedir('calc_templates')  # this is actually the default (from module name, calc.py)
+
+class Calculator(grok.Model):
+    pass
+
+class Sum(grok.View):
+    """Simple view for a model"""
+    grok.context(Calculator)  # this is actually the default (from module)
+    grok.template('sum')  # this is actually the default (from class name)
+    grok.name('sum')  # this is actually the default (from class name)
+    grok.require('zope.Public')  # this is actually the default
+
+    def calculateSum(self):
+        """you can pull this in the template through view/calculateSum"""
+
+    def update(self):    
+        """executed before the template is rendered"""
+        self.sum = self.calculateSum()
+        self.sendEmail()
+
+    def sendEmail(self):
+        """send an email here"""
+
+class PDFSum(grok.View):
+
+    def update(self):
+        pass
+
+    def render(self):
+        return pdfdata
+
+sum = grok.PageTemplate("""\
+<p tal:content="view/calculateSum">...</p>
+<p tal:content="view/precalculatedSum">...</p>
+""")
+
+
+from zope import schema
+
+class Index(grok.Form):
+    """a form
+
+    this is the default view for the Calculator model (because it's
+    called Index)
+    """
+
+    class fields:
+        operand = schema.Int(title=u'Operand')
+        operator = schema.Choice(...)
+        operand2 = schema.Int(...)
+
+    @grok.action('Calculate')
+    def calculate(self, operand, operator, operand2):
+        """it's possible to receive any number of form fields in any
+        order, or just use **kw to receive them all in a dict"""
+        self.result = operator(operand, operand2)
+
+    # this will raise a helpful error message at startup time (encoded
+    # strings)
+    @grok.action('Bääää')
+    def whatever(self, **data):
+        pass
+
+index = grok.PageTemplate("""\
+<form tal:attributes="action request/URL">
+<p tal:condition="exists:view/result">
+  The result is: <span tal:replace="view/result" />
+</p>
+
+XXX render fields
+XXX render actions
+</form>
+""")
+
+class CalculatorXMLRPC(grok.XMLRPC):
+
+    @grok.require('zope.Public')  # this is actually the default
+    def sum(self, operand, operator, operand2):
+        return ...
+
+    @grok.require('something.else')
+    def whatever(self):
+        return ...


Property changes on: grok/branches/darrylcousins-martian-layers/doc/design/views.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/grok2html.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/grok2html.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/grok2html.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,129 @@
+import os
+
+from zope.pagetemplate.pagetemplate import PageTemplate
+
+import docutils.core
+from docutils.writers.html4css1 import HTMLTranslator
+from docutils.writers.html4css1 import Writer
+
+class ZopeTranslator(HTMLTranslator):
+    """
+    The ZopeTranslator extends the base HTML processor for reST.  It
+    augments reST by:
+
+    - Outputs *only* the 'body' parts of the document tree, using the
+    internal docutils structure.
+    """
+
+    def astext(self):
+        """
+        This is where we join the document parts that we want in
+        the output.
+        """
+        # use the title, subtitle, author, date, etc., plus the content
+        body = self.body_pre_docinfo + self.docinfo + self.body
+        return u"".join(body)
+
+
+class ReStructuredTextToHTMLRenderer:
+    """convert from Restructured Text to HTML.
+
+    """
+
+    def __init__(self,content):
+        self.content = content 
+
+    def render(self):
+        settings_overrides = {
+            'halt_level': 6,
+            'output_encoding': 'utf8',
+            'initial_header_level': 2
+        }
+            # 'input_encoding': 'unicode',
+            # 'output_encoding': 'unicode',
+        writer = Writer()
+        writer.translator_class = ZopeTranslator
+        html = docutils.core.publish_string(
+        self.content,
+        writer=writer,settings_overrides=settings_overrides,)
+        return html
+
+
+Menu = [
+        {'href':'index.html','title':u'Home','klass':''},
+        {'href':'about.html','title':u'About','klass':''},
+        {'href':'tutorial.html','title':u'Tutorial','klass':''},
+        ]
+
+class Context:
+    """Set up the context for rendering the rest as html through zpt"""
+
+    id = u''
+    title = u''
+    menu = []
+    content = u''
+
+    def __init__(self, id, title=u''):
+        self.id = id
+        self.title = title
+
+    def restSource(self, source_file):
+        fp = open(source_file)
+        # try to locate a title for the document if not given
+        if not self.title:
+            self.title = fp.readline()
+            if self.title.startswith("="):
+                self.title = fp.readline()
+        fp.close()
+        #rest = codecs.open(source_file,"r",'utf8').read()
+        rest = open(source_file).read()
+        renderer = ReStructuredTextToHTMLRenderer(rest)
+        return renderer.render().strip()
+    
+    def setRestContent(self, source_file):
+        self.content = self.restSource(source_file)
+
+    @property
+    def menu(self):
+        for item in Menu:
+            if item.get('href').split('.')[0] == self.id:
+                item['klass'] = u'selected'
+            else:
+                item['klass'] = u''
+            if not item.get('description', None):
+                item['description'] = item['title']
+        return Menu
+
+def handler_html(pageid, restpath):
+
+# we could rename about_grok.txt to about.txt that we could use only 
+# a pageid to identify the source document and the html result.
+    if os.path.exists(restpath):
+        layout_file = os.path.join('template.pt')
+        layout = PageTemplate()
+        layout.write(open(layout_file,"r").read())
+
+        page = PageTemplate()
+        page.write("""<metal:block use-macro="here/layout/macros/pagelayout" />""")
+
+        context = Context(pageid)
+        context.setRestContent(restpath)
+
+        settings = {}
+        settings["here"] = { "layout": layout }
+        settings["context"] = context
+
+        content = page.pt_render(namespace=settings)
+
+        print content
+
+
+if __name__ == '__main__':
+    import sys
+    args = sys.argv
+
+    if len(args) < 2:
+      print """  Usage: ./grok2html.py pageid restsource > pageid.html
+      Prints to stdout the results of parsing restsource with grok template."""
+    else:
+        handler_html(args[1], args[2])


Property changes on: grok/branches/darrylcousins-martian-layers/doc/grok2html.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/grok2pdf.sh
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/grok2pdf.sh	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/grok2pdf.sh	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+#!/bin/sh
+rst2latex.py --use-latex-toc --stylesheet=style.tex tutorial.txt > tutorial.tex
+pdflatex tutorial.tex


Property changes on: grok/branches/darrylcousins-martian-layers/doc/grok2pdf.sh
___________________________________________________________________
Name: svn:executable
   + 

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/INSTALL.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/INSTALL.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/INSTALL.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,66 @@
+Grok Tutorial Samples installation
+----------------------------------
+
+The Grok tutorial samples make use of a system called buildout. First,
+we'll set up a buildout script that can be reused by all tutorials. Just
+type this in the ``groktut`` directory::
+
+  $ python2.4 bootstrap.py
+
+This will download and install buildout. It will create various
+directories, only one of which, ``eggs``, is important. This directory
+contains all Python eggs shared by the tutorial samples.
+
+Then, we need to install Zope 3 and point the tutorial samples to it.
+First, download Zope 3. We will be showing some Unix style
+instructions here - Windows users should download and run the Zope 3
+installer instead. Go to your preferred installation directory (or
+stay in ``groktut``)::
+
+  $ wget http://www.zope.org/Products/Zope3/3.3.1/Zope-3.3.1.tgz
+  $ tar xvzf Zope-3.3.1.tgz
+  $ cd Zope-3.3.1
+
+We need to tell Zope 3 in which directory it should install itself
+(using ``--prefix``)::
+
+  $ ./configure --prefix=/path/to/zope331
+
+We now make and install it::
+
+  $ make
+  $ make install
+
+Make a note of the Zope 3 installation directory (you too, Windows
+user).
+
+Go back to the ``groktut`` directory and edit the ``buildout_tut.cfg``
+file. Change the ``location`` line to point to your Zope 3
+installation::
+
+  [zope3]
+  # change this to the path to an installed Zope 3 installation
+  location = /path/to/zope331
+
+Now go to the tutorial sample you'd like to look at::
+
+  $ cd an_empty_grok_project
+
+  $ ../buildout -N
+
+The -N option tells the buildout_ system not to look for newer files
+on the network. This greatly speeds up the buildout process if you
+have all required eggs already available, like the second time you run
+the buildout of a sample, as it skips network access.
+
+.. _buildout: http://cheeseshop.python.org/pypi/zc.buildout
+
+You will have a separate Zope instance created for you in each
+tutorial directory you run the buildout script. From the specific
+tutorial directory, you can start up Zope like this::
+
+  $ parts/instance/bin/zopectl fg
+
+Zope should then be running on port 8080 (http://localhost:8080).
+
+Just Ctrl-C when you're done.


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/INSTALL.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,15 @@
+import grok
+  
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Another(grok.Application, grok.Model):
+    pass
+
+class SampleIndex(grok.View):
+    grok.context(Sample)
+    grok.name('index')
+    
+class AnotherIndex(grok.View):
+    grok.context(Another)
+    grok.name('index')


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app_templates/anotherindex.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app_templates/anotherindex.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app_templates/anotherindex.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p>Another index</p>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app_templates/sampleindex.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app_templates/sampleindex.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/app_templates/sampleindex.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p>Sample index</p>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_model/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,11 @@
+import grok
+  
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    pass
+
+class Bye(grok.View):
+    pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app_templates/bye.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app_templates/bye.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app_templates/bye.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p>Bye world!</p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p>Hello world!</p>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_second_view/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    def information(self):
+        return "This is important information!"
+
+class Index(grok.View):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p tal:content="python:context.information()">replaced</p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    def information(self):
+        return "This is important information!"
+
+class Index(grok.View):
+    def reversed_information(self):
+        return ''.join(reversed(self.context.information()))


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,10 @@
+<html>
+<body>
+<p>The information:
+  <span tal:content="python:context.information()">info</span>
+</p>
+<p>The information, reversed: 
+  <span tal:replace="python:view.reversed_information()">info</span>
+</p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/a_view_for_a_model2/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,7 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    pass # see app_templates/index.pt


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,11 @@
+<html>
+<head>
+</head>
+<body>
+  <h1>Congratulations!</h1>
+
+  <p>Your Grok application is up and running.
+  Edit <code>sample/app_templates/index.pt</code> to change
+  this page.</p>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/an_empty_grok_project/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/bootstrap.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/bootstrap.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/bootstrap.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id$
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                     ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/bootstrap.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+[buildout]
+parts = buildout-script
+bin-directory = .
+
+[buildout-script]
+recipe = zc.recipe.egg
+eggs = zc.buildout
+scripts = buildout=buildout

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/buildout_tut.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/buildout_tut.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/buildout_tut.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,50 @@
+[buildout]
+parts = data instance test
+eggs-directory = ../eggs
+
+[zope3]
+# change this to the path to an installed Zope 3 installation
+location = /path/to/zope331
+
+[data]
+recipe = zc.recipe.filestorage
+
+[instance]
+recipe = zc.recipe.zope3instance
+database = data
+user = grok:grok
+eggs = setuptools
+       grok
+       sample
+
+zcml = zope.annotation
+       zope.copypastemove
+       zope.formlib
+       zope.i18n-meta
+       zope.i18n.locales
+       zope.publisher
+       zope.security-meta
+       zope.size
+       zope.traversing
+       zope.traversing.browser
+       zope.app    
+       zope.app-meta
+       zope.app.securitypolicy
+       zope.app.securitypolicy-meta
+       zope.app.authentication
+       zope.app.catalog
+       zope.app.intid
+       zope.app.keyreference
+       zope.app.twisted
+       grok
+       grok-meta
+       sample
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = sample
+extra-paths = parts/zope3/src
+working-directory = parts/instance
+defaults = ['--tests-pattern', '^f?tests$',
+            '-v'
+           ]

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+import grok
+  
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    def render(self):
+        return "ME GROK NO TEMPLATE"


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/completely_python_driven_views/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/containers/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/containers/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/containers/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/containers/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/containers/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/containers/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/containers/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,21 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Entry(grok.Model):
+    def __init__(self, text):
+        self.text = text
+
+class SampleIndex(grok.View):
+    grok.context(Sample)
+    grok.name('index')
+
+    def update(self, name=None, text=None):
+        if name is None or text is None:
+            return
+        self.context[name] = Entry(text)
+
+class EntryIndex(grok.View):
+    grok.context(Entry)
+    grok.name('index')


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app_templates/entryindex.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app_templates/entryindex.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app_templates/entryindex.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+<html>
+<head>
+</head>
+<body>
+  <h2>Entry <span tal:replace="python:context.__name__"></span></h2>
+  <p tal:content="python:context.text"></p>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app_templates/sampleindex.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app_templates/sampleindex.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/app_templates/sampleindex.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,21 @@
+<html>
+<head>
+</head>
+<body>
+  <h2>Existing entries</h2>
+  <ul>
+    <li tal:repeat="key python:context.keys()">
+      <a tal:attributes="href python:view.url(key)" 
+         tal:content="python:key"></a>
+    </li>
+  </ul>
+ 
+  <h2>Add a new entry</h2>
+  <form tal:attributes="action python:view.url()" method="POST">
+    Name: <input type="text" name="name" value="" /><br />
+    Text: <input type="text" name="text" value="" /><br />
+    <input type="submit" value="Add entry" />
+  </form>
+
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/containers/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    def update(self):
+        self.alpha = 2 ** 8
+


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p tal:content="python:view.alpha">result</p>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/doing_some_calculation_before_viewing_a_page/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/empty/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/empty/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/empty/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/empty/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/empty/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/empty/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/empty/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,4 @@
+import grok
+  
+class Sample(grok.Application, grok.Container):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/empty/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,12 @@
+import grok
+  
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    grok.context(Sample)
+
+class Bye(grok.View):
+    grok.context(Sample)
+    
+


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app_templates/bye.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app_templates/bye.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app_templates/bye.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p>Bye world!</p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p>Hello world!</p>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/explicitly_associating_a_view_with_a_model/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+import grok
+  
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    def some_html(self):
+        return "<b>ME GROK BOLD</b>"
+


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p tal:content="structure python:view.some_html()"></p>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/generating_html_from_python/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+import grok
+  
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p tal:content="python: 1 + 1">this is replaced</p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/making_our_page_dynamic/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,7 @@
+import grok
+  
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p>Hello world!</p>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/publishing_a_simple_web_page/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    def update(self, value1, value2):
+        self.sum = int(value1) + int(value2)


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p tal:content="python:view.sum">sum</p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    def update(self, value1=0, value2=0):
+        self.sum = int(value1) + int(value2)


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p tal:content="python:view.sum">sum</p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/reading_url_parameters2/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,14 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    text = 'default text'
+
+class Index(grok.View):
+    pass
+
+class Edit(grok.View):
+    def update(self, text=None):
+        if text is None:
+            return
+        self.context.text = text
+        self.redirect(self.url('index'))


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app_templates/edit.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app_templates/edit.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app_templates/edit.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+<html>
+<body>
+<form tal:attributes="action view/url" method="POST">
+Text to store: <input type="text" name="text" value="" /><br />
+<input type="submit" value="Store" />
+</form>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,6 @@
+<html>
+<body>
+<p>The text: <span tal:replace="python:context.text">text</span></p>
+<p><a tal:attributes="href python:view.url('edit')">Edit this page</a></p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/redirection/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,11 @@
+import grok
+  
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    def render(self):
+        self.response.setHeader('Content-Type',
+                                'text/xml; charset=UTF-8')
+        return "<doc>Some XML</doc>"
+


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/setting_the_content_type/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,14 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    text = 'default text'
+
+class Index(grok.View):
+    pass
+
+class Edit(grok.View):
+    def update(self, text=None):
+        if text is None:
+            return
+        self.context.text = text
+        self.redirect(self.url('index'))


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app_templates/edit.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app_templates/edit.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app_templates/edit.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+<html>
+<body>
+<form tal:attributes="action view/url" method="POST">
+Text to store: <input type="text" name="text" tal:attributes="value python:context.text" value="" /><br />
+<input type="submit" value="Store" />
+</form>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,6 @@
+<html>
+<body>
+<p>The text: <span tal:replace="python:context.text">text</span></p>
+<p><a tal:attributes="href python:view.url('edit')">Edit this page</a></p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/showing_the_value_in_the_form/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    def update(self, value1=0, value2=0):
+        self.sum = int(value1) + int(value2)


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,10 @@
+<html>
+<body>
+<form tal:attributes="action python:view.url()" method="GET">
+  Value 1: <input type="text" name="value1" value="" /><br />
+  Value 2: <input type="text" name="value2" value="" /><br />
+  <input type="submit" value="Sum!" />
+</form>
+<p>The sum is: <span tal:replace="python:view.sum">sum</span></p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,14 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    def update(self, value1=None, value2=None):
+        try:
+            value1 = int(value1)
+            value2 = int(value2)
+        except (TypeError, ValueError):
+            self.sum = "No sum"
+            return
+        self.sum = value1 + value2


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,10 @@
+<html>
+<body>
+<form tal:attributes="action python:view.url()" method="GET">
+  Value 1: <input type="text" name="value1" value="" /><br />
+  Value 2: <input type="text" name="value2" value="" /><br />
+  <input type="submit" value="Sum!" />
+</form>
+<p>The sum is: <span tal:replace="python:view.sum">sum</span></p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/simple_forms2/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,7 @@
+import grok
+  
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+<html>
+<head>
+<link rel="stylesheet" type="text/css" 
+      tal:attributes="href static/style.css" />
+</head>
+<body>
+<p>Hello world!</p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/static/style.css
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/static/style.css	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/static_resources_for_our_web_page/src/sample/static/style.css	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+body {
+    background-color: #FF0000;
+}

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,13 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    text = 'default text'
+
+class Index(grok.View):
+    pass
+
+class Edit(grok.View):
+    def update(self, text=None):
+        if text is None:
+            return
+        self.context.text = text


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app_templates/edit.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app_templates/edit.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app_templates/edit.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+<html>
+<body>
+<form tal:attributes="action view/url" method="POST">
+Text to store: <input type="text" name="text" value="" /><br />
+<input type="submit" value="Store" />
+</form>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p>The text: <span tal:replace="python:context.text">text</span></p>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/storing_data/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,17 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    def __init__(self):
+        super(Sample, self).__init__()
+        self.list = []
+    
+class Index(grok.View):
+    pass
+
+class Edit(grok.View):
+    def update(self, text=None):
+        if text is None:
+            return
+        # this code has a BUG!
+        self.context.list.append(text)
+        self.redirect(self.url('index'))


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app_templates/edit.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app_templates/edit.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app_templates/edit.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+<html>
+<body>
+<form tal:attributes="action view/url" method="POST">
+Text to store: <input type="text" name="text" value="" /><br />
+<input type="submit" value="Store" />
+</form>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+<html>
+<body>
+We store the following texts:
+<ul>
+  <li tal:repeat="text python:context.list" tal:content="text"></li>
+</ul>
+<a tal:attributes="href python:view.url('edit')">Add a text</a>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,17 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    def __init__(self):
+        super(Sample, self).__init__()
+        self.list = []
+    
+class Index(grok.View):
+    pass
+
+class Edit(grok.View):
+    def update(self, text=None):
+        if text is None:
+            return
+        self.context.list.append(text)
+        self.context._p_changed = True
+        self.redirect(self.url('index'))


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app_templates/edit.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app_templates/edit.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app_templates/edit.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+<html>
+<body>
+<form tal:attributes="action view/url" method="POST">
+Text to store: <input type="text" name="text" value="" /><br />
+<input type="submit" value="Store" />
+</form>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+<html>
+<body>
+We store the following texts:
+<ul>
+  <li tal:repeat="text python:context.list" tal:content="text"></li>
+</ul>
+<a tal:attributes="href python:view.url('edit')">Add a text</a>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence2/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+import grok
+
+class Sample(grok.Application, grok.Container):
+    def __init__(self):
+        super(Sample, self).__init__()
+        self.list = []
+
+    def addText(self, text):
+        self.list.append(text)
+        self._p_changed = True
+        
+class Index(grok.View):
+    pass
+
+class Edit(grok.View):
+    def update(self, text=None):
+        if text is None:
+            return
+        self.context.addText(text)
+        self.redirect(self.url('index'))


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app_templates/edit.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app_templates/edit.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app_templates/edit.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+<html>
+<body>
+<form tal:attributes="action view/url" method="POST">
+Text to store: <input type="text" name="text" value="" /><br />
+<input type="submit" value="Store" />
+</form>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+<html>
+<body>
+We store the following texts:
+<ul>
+  <li tal:repeat="text python:context.list" tal:content="text"></li>
+</ul>
+<a tal:attributes="href python:view.url('edit')">Add a text</a>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/the_rules_of_persistence3/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[buildout]
+develop = .
+extends = ../buildout_tut.cfg
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = 0.0
+
+setup(name='Sample',
+      version=version,
+      description="",
+      long_description="""\
+""",
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[], 
+      keywords="",
+      author="",
+      author_email="",
+      url="",
+      license="",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,10 @@
+import grok
+from datetime import datetime
+
+class Sample(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):    
+    def current_datetime(self):
+        now = datetime.now()
+        return now.strftime('%Y-%m-%d %H:%M')


Property changes on: grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/app_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/app_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/app_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p tal:content="python:view.current_datetime()">Hello world!</p>
+</body>
+</html>
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/groktut/using_view_methods/src/sample/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />

Added: grok/branches/darrylcousins-martian-layers/doc/index.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/index.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/index.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,121 @@
+=============
+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
+
+
+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/archive/2007/02/11/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 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.
+
+* `Martijn Faassen's blog entry`_ details the first Grok sprint.
+* `Jan-Wijbrand Kolman blogged`_ about the second Grok sprint, and `Martijn Faassen
+  blogged`_ about it as well.
+
+.. _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


Property changes on: grok/branches/darrylcousins-martian-layers/doc/index.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/doc/naming_conventions.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/naming_conventions.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/naming_conventions.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,33 @@
+Grok naming conventions
+-----------------------
+
+Zope 3 used to follow PEP 8, but then PEP 8 changed so that
+methodNames() is deprecated in favor of method_names().
+
+Grok aims to be mostly consistent with Zope 3, but does make some
+changes in the direction of PEP 8.
+
+modulenames - module and package names are all lower case, no
+underscores
+              
+ClassNames - CamelCase (Zope 3 + PEP 8)
+
+methodNames - camelCase: follow Zope 3 conventions. We work a lot with Zope 3
+              classes and sometimes subclass.
+
+attribute_names - Zope 3 + PEP 8
+
+class_annotations - we break with Zope 3 tradition
+                    (grok.local_utility() versus implementsOnly()). 
+                    This makes class annotations stand out a bit
+                    more and is more consistent with the use of
+                    class-level attribute names for customization
+                    as well (as in formlib).
+
+top_level_functions - Zope 3 uses camel case (getUtility()).  Grok
+                      uses underscores for top-level functions that
+                      define class annotations. Grok internally has also
+                      been using underscores for functions defined
+                      internally. So far we have avoided exposing them
+                      to the outside world. If you need to expose
+                      one of these, bring it up on the grok-dev mailing list.


Property changes on: grok/branches/darrylcousins-martian-layers/doc/naming_conventions.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/doc/reference/README.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/reference/README.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/reference/README.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,43 @@
+=========================
+The grok reference manual
+=========================
+
+The manual is written using LaTeX with support for the Python documentation
+markup. The tex sources can be compiled to HTML and PDF. To build the manual,
+you need the 'mkhowto' script from a recent Python source distribution.
+
+Build the HTML
+--------------
+
+Compiling the sources into HTML::
+
+  $ mkhowto --html reference.tex
+
+The directory 'reference/' keeps all files required to display the manual after
+that call and can be put on a static webserver.
+
+Build the PDF
+-------------
+
+The file 'reference.pdf' will contain the PDF version of the manual after this
+call::
+
+  $ mkhowto --pdf reference.tex
+
+Installing prerequisites on Debian and Ubuntu systems
+-----------------------------------------------------
+
+On recent Debian and Ubuntu systems, the following packages provide the
+required toolset for compiling the sources.
+
+The basic LaTeX infrastructure::
+
+  $ sudo apt-get install tetex-base tetex-bin tetex-extra latex2html
+
+The python-dev package provides the mkhowto script::
+
+  $ sudo apt-get install python2.4-dev
+
+This script will be located in::
+
+  /usr/lib/python2.4/doc/tools/mkhowto


Property changes on: grok/branches/darrylcousins-martian-layers/doc/reference/README.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/doc/reference/components.tex
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/reference/components.tex	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/reference/components.tex	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,238 @@
+\chapter{Components}
+
+The \module{grok} module defines a set of components that provide basic Zope 3
+functionality in a convenient way.
+
+\section{\class{grok.Adapter}}
+
+  Implementation, configuration, and registration of Zope 3 adapters.
+
+  \begin{classdesc*}{grok.Adapter}
+    Base class to define an adapter. Adapters are automatically registered when
+    a module is "grokked".
+
+    \begin{memberdesc}{context}
+      The adapted object.
+    \end{memberdesc}
+
+  \begin{bf}Directives:\end{bf}
+
+  \begin{itemize}
+    \item[\function{grok.context(context_obj_or_interface)}] Maybe required.
+    Identifies the type of objects or interface for the adaptation.
+
+    If Grok can determine a context for adaptation from the module, this
+    directive can be omitted. If the automatically determined context is not
+    correct, or if no context can be derived from the module the directive is
+    required.
+
+    \item[\function{grok.implements(*interfaces)}] Required. Identifies the
+    interface(s) the adapter implements.
+
+    \item[\function{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.
+
+    \item[\function{grok.provides(name)}] Maybe required. If the adapter
+    implements more than one interface, \function{grok.provides} is required to
+    disambiguate for what interface the adapter will be registered.
+  \end{itemize}
+  \end{classdesc*}
+
+  \begin{bf}Example:\end{bf}
+
+  \begin{verbatim}
+import grok
+from zope import interface
+
+class Cave(grok.Model):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)
+
+home = IHome(cave)
+  \end{verbatim}
+
+  \begin{bf}Example 2:\end{bf}
+
+  \begin{verbatim}
+import grok
+from zope import interface
+
+class Cave(grok.Model):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)
+    grok.name('home')
+
+from zope.component import getAdapter
+home = getAdapter(cave, IHome, name='home')
+  \end{verbatim}
+
+\section{\class{grok.AddForm}}
+
+\section{\class{grok.Annotation}}
+
+\section{\class{grok.Application}}
+
+\section{grok.ClassGrokker}
+
+\section{\class{grok.Container}}
+
+  \begin{classdesc*}{grok.Container}
+    Mixin base class to define a container object. The container implements the
+    zope.app.container.interfaces.IContainer interface using a BTree, providing
+    reasonable performance for large collections of objects.
+  \end{classdesc*}
+
+\section{\class{grok.DisplayForm}}
+
+\section{\class{grok.EditForm}}
+
+\section{\class{grok.Form}}
+
+\section{\class{grok.GlobalUtility}}
+
+  \begin{classdesc*}{grok.GlobalUtility}
+    Base class to define a globally registered utility. Global utilities are
+    automatically registered when a module is "grokked".
+
+  \begin{bf}Directives:\end{bf}
+
+  \begin{itemize}
+    \item[\function{grok.implements(*interfaces)}] Required. Identifies the
+    interfaces(s) the utility implements.
+
+    \item[\function{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.
+
+    \item[\function{grok.provides(name)}] Maybe required. If the global utility
+    implements more than one interface, \function{grok.provides} is required to
+    disambiguate for what interface the global utility will be registered.
+  \end{itemize}
+  \end{classdesc*}
+
+\section{\class{grok.Indexes}}
+
+\section{grok.InstanceGrokker}
+
+\section{\class{grok.JSON}}
+
+\section{\class{grok.LocalUtility}}
+
+  \begin{classdesc*}{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
+    \function{grok.local_utility} directive.
+
+  \begin{bf}Directives:\end{bf}
+
+  \begin{itemize}
+    \item[\function{grok.implements(*interfaces)}] Optional. Identifies the
+    interfaces(s) the utility implements.
+
+    \item[\function{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.
+
+    \item[\function{grok.provides(name)}] Maybe required. If the local utility
+    implements more than one interface or if the implemented interface cannot
+    be determined, \function{grok.provides} is required to disambiguate for
+    what interface the local utility will be registered.
+  \end{itemize}
+  \end{classdesc*}
+
+  \begin{seealso}
+  Local utilities need to be registered in the context of \class{grok.Site} or
+  \class{grok.Application} using the \function{grok.local_utility} directive.
+  \end{seealso}
+
+\section{\class{grok.Model}}
+
+  Base class to define an application "content" or model object. Model objects
+  provide persistence and containment.
+
+\section{grok.ModuleGrokker}
+
+\section{\class{grok.MultiAdapter}}
+
+  \begin{classdesc*}{grok.MultiAdapter}
+    Base class to define a multi adapter. MultiAdapters are automatically
+    registered when a module is "grokked".
+
+  \begin{bf}Directives:\end{bf}
+
+  \begin{itemize}
+    \item[\function{grok.adapts(*objects_or_interfaces)}] Required. Identifies
+    the combination of types of objects or interfaces for the adaptation.
+
+    \item[\function{grok.implements(*interfaces)}] Required. Identifies the
+    interfaces(s) the adapter implements.
+
+    \item[\function{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.
+
+    \item[\function{grok.provides(name)}] Maybe required. If the adapter
+    implements more than one interface, \function{grok.provides} is required to
+    disambiguate for what interface the adapter will be registered.
+  \end{itemize}
+  \end{classdesc*}
+
+  \begin{bf}Example:\end{bf}
+
+  \begin{verbatim}
+import grok
+from zope import interface
+
+class Fireplace(grok.Model):
+    pass
+
+class Cave(grok.Model):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.MultiAdapter):
+    grok.adapts(Cave, Fireplace)
+    grok.implements(IHome)
+
+    def __init__(self, cave, fireplace):
+        self.cave = cave
+        self.fireplace = fireplace
+
+home = IHome(cave, fireplace)
+  \end{verbatim}
+
+\section{grok.PageTemplate}
+
+\section{grok.PageTemplateFile}
+
+\section{\class{grok.Site}}
+
+  Base class to define an site object. Site objects provide persistence and
+  containment.
+
+\section{\class{grok.Traverser}}
+
+\section{\class{grok.View}}
+
+\section{\class{grok.XMLRPC}}

Added: grok/branches/darrylcousins-martian-layers/doc/reference/core.tex
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/reference/core.tex	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/reference/core.tex	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,50 @@
+\chapter{Core}
+
+The \module{grok} module defines a few functions to interact with grok itself.
+
+
+\section{\function{grok.grok} -- Grok a package or module}
+
+    \begin{funcdesc}{grok}{dotted_name}
+
+    Grokking a package or module activates the contained components (like
+    models, views, adapters, templates, etc.) and registers them with Zope 3's
+    component architecture.
+
+    The \var{dotted_name} must specify either a Python module or package
+    that is available from the current PYTHONPATH.
+
+    Grokking a module:
+
+    \begin{enumerate}
+
+        \item Scan the module for known components: models, adapters,
+              utilities, views, traversers, templates and subscribers.
+
+        \item Check whether a directory with file system templates
+              exists (\file{<modulename>_templates}).  If it exists,
+              load the file system templates into the template
+              registry for this module.
+
+        \item Determine the module context. 
+
+        \item Register all components with the Zope 3 component architecture.
+
+        \item Initialize schemata for registered models
+
+    \end{enumerate}
+
+    Grokking a package:
+
+    \begin{enumerate}
+        \item Grok the package as a module.
+
+        \item Check for a static resource directory (\file{static})
+          and register it if it exists.
+
+        \item Recursively grok all sub-modules and sub-packages.
+
+    \end{enumerate}
+
+    \end{funcdesc}
+

Added: grok/branches/darrylcousins-martian-layers/doc/reference/decorators.tex
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/reference/decorators.tex	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/reference/decorators.tex	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,21 @@
+\chapter{Decorators}
+
+grok uses a few decorators to register functions or methods for specific
+functionality.
+
+    \section{\function{grok.subscribe} -- Register a function as a subscriber
+    for an event}
+
+        \begin{funcdesc}{subscribe}{*classes_or_interfaces}
+
+        Declare that the decorated function subscribes to an event or a
+        combination of objects and events and register it.
+
+        Applicable on module-level for functions. Requires at least one class
+        or interface as argument.
+
+        (Similar to Zope 3's \function{subscriber} decorator, but automatically
+        performs the registration of the component.)
+        \end{funcdesc}
+
+    \section{grok.action}

Added: grok/branches/darrylcousins-martian-layers/doc/reference/directives.tex
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/reference/directives.tex	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/reference/directives.tex	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,146 @@
+\chapter{Directives}
+
+The \module{grok} module defines a set of directives that allow you to
+configure and register your components. Most directives assume a default, based
+on the environment of a module. (For example, a view will be automatically
+associated with a model if the association can be made unambigously.)
+
+If no default can be assumed for a value, grok will explicitly tell you what is
+missing and how you can provide a default or explicit assignment for the value
+in question.
+
+    \section{\function{grok.AutoFields}}
+
+        \begin{funcdesc}{grok.AutoFields}{*arg}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.adapts}}
+
+        \begin{funcdesc}{grok.adapts}{*interfaces}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.baseclass}}
+
+        \begin{funcdesc}{grok.baseclass}{*interfaces}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.define_permission}}
+
+        \begin{funcdesc}{grok.define_permission}{*arg}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.Fields}}
+
+        \begin{funcdesc}{grok.Fields}{*arg}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.implements}}
+
+        \begin{funcdesc}{grok.implements}{*arg}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.context}}
+
+        \begin{funcdesc}{grok.context}{*arg}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.global_utility}}
+
+        \begin{funcdesc}{grok.global_utility}{*arg}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.name}}
+
+        \begin{funcdesc}{grok.name}{*arg}
+        foobar
+        \end{funcdesc}
+
+        Used to associate a component with a name. Typically this directive is
+        optional. The default behaviour when no name is given depends on the
+        component.
+
+    \section{\function{grok.local_utility}}
+
+        \begin{funcdesc}{grok.local_utility}{*arg}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.provides}}
+
+        \begin{funcdesc}{grok.provides}{*arg}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.resourcedir --- XXX Not implemented yet}}
+
+        \begin{funcdesc}{grok.resourcedir}{*arg}
+        foobar
+        \end{funcdesc}
+
+        Resource directories are used to embed static resources like HTML-,
+        JavaScript-, CSS- and other files in your application.
+
+        XXX insert directive description here (first: define the name, second:
+        describe the default behaviour if the directive isn't given)
+
+        A resource directory is created when a package contains a directory
+        with the name \file{static}. All files from this directory become
+        accessible from a browser under the URL
+        \file{http://<servername>/++resource++<packagename>/<filename>}.
+
+        \begin{bf}Example:\end{bf} The package \module{a.b.c} is grokked and
+        contains a directory \file{static} which contains the file
+        \file{example.css}. The stylesheet will be available via
+        \file{http://<servername>/++resource++a.b.c/example.css}.
+
+        \begin{notice}
+        A package can never have both a \file{static} directory and a Python
+        module with the name \file{static.py} at the same time. grok will
+        remind you of this conflict when grokking a package by displaying an
+        error message.
+        \end{notice}
+
+        \subsection{Linking to resources from templates}
+
+            grok provides a convenient way to calculate the URLs to static
+            resource using the keyword \keyword{static} in page templates:
+
+            \begin{verbatim}
+<link rel="stylesheet" tal:attributes="href static/example.css" type="text/css">
+            \end{verbatim}
+
+            The keyword \keyword{static} will be replaced by the reference to
+            the resource directory for the package in which the template was
+            registered.
+
+    \section{\function{grok.require}}
+
+        \begin{funcdesc}{grok.require}{*arg}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.site}}
+
+        \begin{funcdesc}{grok.site}{*arg}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.template}}
+
+        \begin{funcdesc}{grok.template}{*arg}
+        foobar
+        \end{funcdesc}
+
+    \section{\function{grok.templatedir}}
+
+        \begin{funcdesc}{grok.templatedir}{*arg}
+        foobar
+        \end{funcdesc}

Added: grok/branches/darrylcousins-martian-layers/doc/reference/events.tex
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/reference/events.tex	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/reference/events.tex	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,33 @@
+\chapter{Events}
+
+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.
+
+    \section{grok.IContainerModifiedEvent}
+
+    \section{grok.IObjectAddedEvent}
+
+    \section{grok.IObjectCopiedEvent}
+
+    \section{grok.IObjectCreatedEvent}
+
+    \section{grok.IObjectModifiedEvent}
+
+    \section{grok.IObjectMovedEvent}
+
+    \section{grok.IObjectRemovedEvent}
+
+    \section{grok.ContainerModifiedEvent}
+
+    \section{grok.ObjectAddedEvent}
+
+    \section{grok.ObjectCopiedEvent}
+
+    \section{grok.ObjectCreatedEvent}
+
+    \section{grok.ObjectModifiedEvent}
+
+    \section{grok.ObjectMovedEvent}
+
+    \section{grok.ObjectRemovedEvent}

Added: grok/branches/darrylcousins-martian-layers/doc/reference/exceptions.tex
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/reference/exceptions.tex	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/reference/exceptions.tex	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,49 @@
+\chapter{Exceptions}
+
+grok tries to inform you about errors early and with as much guidance as
+possible. grok can detect some errors already while importing a module, which
+will lead to the \class{GrokImportError}.  Other errors require more context
+and can only be detected while executing the \function{grok} function.
+
+    \section{\class{grok.GrokImportError} -- errors while importing a module}
+
+    This exception is raised if a grok-specific problem was found while
+    importing a module of your application. \class{GrokImportError} means there
+    was a problem in how you are using a part of grok. The error message tries
+    to be as informative as possible tell you why something went wrong and how
+    you can fix it.
+
+    \class{GrokImportError} is a subclass of Python's \class{ImportError}.
+
+    Examples of situations in which a GrokImportError occurs:
+
+    \begin{itemize}
+        \item Using a directive in the wrong context (e.g. grok.templatedir on
+        class-level instead of module-level.)
+        \item Using a decorator with wrong arguments (e.g. grok.subscribe
+        without any argument)
+        \item \ldots
+    \end{itemize}
+
+    \section{\class{grok.GrokError} -- errors while grokking a module}
+
+    This exception is raised if an error occurs while grokking a module.
+
+    Typically a \class{GrokError} will be raised if one of your modules uses a
+    feature of grok that requires some sort of unambigous context to establish
+    a reasonable default.
+
+    For example, the \class{grok.View} requires exactly one model to be defined
+    locally in the module to assume a default module to be associated with.
+    Having no model defined, or more than one model, will lead to an error
+    because the context is either underspecified or ambigous.
+
+    The error message of a \class{GrokError} will include the reason for the
+    error, the place in your code that triggered the error, and a hint, to help
+    you fix the error.
+
+    \begin{classdesc}{GrokError}{Exception}
+        \begin{memberdesc}{component}
+            The component that was grokked and triggered the error.
+        \end{memberdesc}
+    \end{classdesc}

Added: grok/branches/darrylcousins-martian-layers/doc/reference/functions.tex
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/reference/functions.tex	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/reference/functions.tex	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,72 @@
+\chapter{Functions}
+
+The \module{grok} module provides a number of convenience functions to aid in
+common tasks.
+
+  \section{\function{grok.getSite}}
+
+    \begin{funcdesc}{grok.getSite}{}
+    Get the current site object.
+
+      \begin{seealso}
+      Site objects are instances of \class{grok.Site} and/or
+      \class{grok.Application}.
+      \end{seealso}
+
+      \begin{seealso}
+      \seetitle
+      [http://worldcookery.com/WhereToBuy]
+      {Web Component Development With Zope 3, second edition}
+      {By Philiip von Weitershaussen; Chapter 18 describes the use of Site
+      objects.}
+      \end{seealso}
+
+    \end{funcdesc}
+
+  \section{\function{grok.notify}}
+
+    \begin{funcdesc}{grok.notify}{event}
+    Send \var{event} to event subscribers.
+
+    Example:
+\begin{verbatim}
+import grok
+
+class Mammoth(object):
+    def __init__(self, name):
+        self.name = name
+
+manfred = Mammoth('manfred')
+
+grok.notify(grok.ObjectCreatedEvent(manfred))
+\end{verbatim}
+
+      \begin{seealso}
+      Grok events provide a selection of common event types.
+      \end{seealso}
+
+      \begin{seealso}
+      \seetitle
+      [http://worldcookery.com/WhereToBuy]
+      {Web Component Development With Zope 3, second edition}
+      {By Philiip von Weitershaussen; Chapter 16 describes the Zope 3 event
+      system.}
+      \end{seealso}
+
+    \end{funcdesc}
+
+  \section{\function{grok.url}}
+
+    \begin{funcdesc}{grok.url}{request, object, \optional{, name}}
+    Construct a URL for the given \var{request} and \var{object}.
+
+    \var{name} may be a string that gets appended to the object URL. Commonly
+    used to construct an URL to a particular view on the object.
+
+    This function returns the constructed URL as a string.
+
+      \begin{seealso}
+      View classes derived from \class{grok.View} have a similar \method{url}
+      method for constructing URLs.
+      \end{seealso}
+    \end{funcdesc}

Added: grok/branches/darrylcousins-martian-layers/doc/reference/model.tex
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/reference/model.tex	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/reference/model.tex	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+\chapter{grok.Model}
+
+  \section{Models}

Added: grok/branches/darrylcousins-martian-layers/doc/reference/reference.tex
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/reference/reference.tex	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/reference/reference.tex	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,71 @@
+% Complete documentation on the extended LaTeX markup used for Python
+% documentation is available in ``Documenting Python'', which is part
+% of the standard documentation for Python.  It may be found online
+% at:
+%
+%     http://www.python.org/doc/current/doc/doc.html
+
+\documentclass{manual}
+\RequirePackage[latin9]{inputenc}
+\usepackage{graphicx}
+
+\title{grok reference}
+
+% Please at least include a long-lived email address;
+% the rest is at your discretion.
+\authoraddress{
+    The grok team\\
+    Email: <grok-dev at zope.org>
+}
+
+\date{\today}   % update before release!
+                % Use an explicit date so that reformatting
+                % doesn't cause a new date to be used.  Setting
+                % the date to \today can be used during draft
+                % stages to make it easier to handle versions.
+
+\release{unreleased}      % release version; this is used to define the
+                          % \version macro
+
+\makeindex          % tell \index to actually write the .idx file
+
+\begin{document}
+
+\maketitle
+
+    \begin{quote}
+    ``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
+    \end{quote}
+
+\begin{abstract}
+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.
+\end{abstract}
+
+\tableofcontents
+
+\include{core}
+
+\include{components}
+
+\include{directives}
+
+\include{decorators}
+
+\include{functions}
+
+\include{events}
+
+\include{exceptions}
+
+\end{document}

Added: grok/branches/darrylcousins-martian-layers/doc/release.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/release.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/release.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,27 @@
+Continuous releases from SVN
+----------------------------
+
+A note from Philipp to the mailing list, put here so we don't forget this
+useful information:
+
+I've now enabled grok and grokproject to register themselves as
+revision number-based releases from SVN. That means the version number
+is now composed the following way:
+
+  ${next_stable_release_version}dev-r{svn_revision_number}
+
+The advantage of that is that we can now receive automatic updates
+whenever we reregister a newer "version" of grok (based on a higher
+revision number).
+
+I've also uploaded eggs and tarballs so that people who don't have
+subversion can still install grok and grokproject (useful for Windows
+folks). That means if you easy_install grok right now, it will install
+it from the uploaded egg (you won't get the subversion HEAD
+anymore). If you still want to get it straight from subversion,
+easy_install grok==dev.
+
+After changes to grok itself, you can register and upload a new
+"release" to the Cheeseshop with
+
+  python setup.py register sdist bdist_egg upload


Property changes on: grok/branches/darrylcousins-martian-layers/doc/release.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/doc/style.tex
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/style.tex	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/style.tex	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,74 @@
+% latex include file for docutils latex writer
+% --------------------------------------------
+%
+% CVS: $Id: style.tex,v 1.1 2004/01/23 21:17:32 faassen Exp $
+%
+% This is included at the end of the latex header in the generated file,
+% to allow overwriting defaults, although this could get hairy.
+% Generated files should process well standalone too, LaTeX might give a
+% message about a missing file.
+
+% donot indent first line of paragraph.
+\setlength{\parindent}{0pt}
+\setlength{\parskip}{5pt plus 2pt minus 1pt}
+
+% sloppy
+% ------
+% Less strict (opposite to default fussy) space size between words. Therefore
+% less hyphenation.
+\sloppy
+
+% fonts
+% -----
+% times for pdf generation, gives smaller pdf files.
+%
+% But in standard postscript fonts: courier and times/helvetica do not fit.
+% Maybe use pslatex.
+\usepackage{times}
+
+% pagestyle
+% ---------
+% headings might put section titles in the page heading, but not if
+% the table of contents is done by docutils.
+% If pagestyle{headings} is used, \geometry{headheight=10pt,headsep=1pt}
+% should be set too.
+%\pagestyle{plain}
+%
+% or use fancyhdr (untested !)
+\usepackage{fancyhdr}
+\pagestyle{fancy}
+\addtolength{\headheight}{\baselineskip}
+\renewcommand{\sectionmark}[1]{\markboth{#1}{}}
+\renewcommand{\subsectionmark}[1]{\markright{#1}}
+\fancyhf{}
+\fancyhead[LE,RO]{\bfseries\textsf{\thepage}}
+\fancyhead[LO]{\textsf{\footnotesize\rightmark}}
+\fancyhead[RE]{\textsc{\textsf{\footnotesize\leftmark}}}
+%\fancyfoot[LE,RO]{\bfseries\textsf{\scriptsize Docutils}}
+%\fancyfoot[RE,LO]{\textsf{\scriptsize\today}}
+
+% geometry 
+% --------
+% = papersizes and margins
+%\geometry{a4paper,twoside,tmargin=1.5cm,
+%          headheight=1cm,headsep=0.75cm}
+
+% Do section number display
+% -------------------------
+%\makeatletter
+%\def\@seccntformat#1{}
+%\makeatother
+% no numbers in toc
+%\renewcommand{\numberline}[1]{}
+
+
+% change maketitle
+% ----------------
+%\renewcommand{\maketitle}{
+%  \begin{titlepage}
+%    \begin{center}
+%    \textsf{TITLE \@title} \\
+%	Date: \today
+%    \end{center}
+%  \end{titlepage}
+%}

Added: grok/branches/darrylcousins-martian-layers/doc/template.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/template.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/template.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,68 @@
+<metal:block define-macro="pagelayout">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title tal:content="context/title" />
+  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+  <meta name="description" content="Grok - now even cavemen can use Zope3" />
+  <meta name="keywords" content="Grok, internet, zope, zope3, software, web apps, web applications, python" />
+	<style type="text/css"><!-- @import url(./resources/grok.css); --></style>
+</head>
+
+<body>
+<div class="header">
+	
+	<a href="http://grok.zope.org">
+	<img src="./resources/grok-header.jpg" alt="GROK"/></a>
+	<ul id="navigation">
+        <li tal:repeat="item context/menu">
+            <a tal:content="item/title"
+               tal:attributes="title item/description;
+                               class item/klass;
+                               href item/href">link</a></li>
+  </ul>
+</div>
+
+
+<div class="roundcont">
+	
+  <div class="roundtop">
+    <img src="./resources/corner-topleft.jpg" alt="" 
+           width="45" height="45" class="corner" 
+           style="display: none" />
+  </div>
+
+  <div class="content">
+
+          <tal:block replace="structure context/content" />
+
+  </div>
+
+  <div class="roundbottom">
+     <img src="./resources/corner-bottomleft.jpg" alt="" 
+     width="45" height="45" class="corner" 
+     style="display: none" />
+  </div>
+
+</div>
+
+<div class="footer">
+	
+	<table><tr><td>
+	Grok cooks around the campfire of <br />
+	<a href="http://wiki.zope.org/zope3/FrontPage"><img src="./resources/zopelogo.gif" alt="Zope" style="padding: 0.5em;" /></a>
+	</td><td>
+	 and roams free on the savannah of<br />
+	<a href="http://www.python.org"><img src="./resources/python-logo.gif" style="padding: 0.5em;" alt="Python" /></a>
+	</td></tr>
+	</table>
+
+	<p>Hosting provided by <a href="http://quintagroup.com/"><b>Quintagroup</b></a></p>
+</div>
+
+</body>
+</html>
+</metal:block>
+

Added: grok/branches/darrylcousins-martian-layers/doc/tutorial.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/tutorial.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/tutorial.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,1376 @@
+=============
+Grok tutorial
+=============
+
+.. raw:: html
+
+   Also available as <a href="./tutorial.pdf">PDF</a>.
+
+.. contents::
+
+Welcome to the Grok tutorial!
+=============================
+
+.. sidebar:: Getting started with Zope Page Templates
+
+  You can find introductions and more information about Zope Page
+  Templates (ZPT, sometimes also called TAL) in various places:
+
+    http://plone.org/documentation/tutorial/zpt
+
+    http://wiki.zope.org/ZPT/FrontPage
+
+  Note that some of the information in these introductions may refer
+  to concepts not available in Grok or Zope 3, in particular variables
+  like ``here`` or ``template``. The basic principles will work with
+  Zope 3 (and Grok) however; try reading ``context`` or ``view``
+  instead.
+
+Grok is a powerful and flexible web application framework for Python
+developers.  In this tutorial we will show you the various things you
+can do with Grok, and how Grok can help you build your web
+application. We'll start out simple, and will slowly go to more
+complex usage patterns.
+
+All you're expected to know is the Python programming language and an
+understanding of basic web programming (HTML, forms, URLs). It also
+helps if you are familiar with Zope Page Templates, though most of the
+examples should be fairly obvious if you are already familiar with
+another templating language.
+
+We recommend beginners to follow the tutorial from top to bottom. The
+tutorial is designed to explain important concepts in order and slowly
+builds up from there.
+
+If you are more experienced, or just curious, you may want to skip
+around instead and read the pieces which interest you most. If
+something is unclear, you can always backtrack to previous sections.
+
+Grok is based on Zope 3 and is compatible with Zope 3, but you do not
+need to know Zope 3 (or Zope 2) at all to follow this tutorial. Grok
+builds on existing Zope 3 technology but exposes it in a different way
+to the developer. We believe Grok makes developing with Zope 3
+technology easier and more fun for beginners and experienced
+developers alike.
+
+Getting started with Grok
+=========================
+
+This chapter will help you get up and running with Grok, using the
+``grokproject`` tool. We create a new project with ``grokproject``,
+tell you how to get that project running so you can access it with a
+web browser.
+
+Setting up grokproject
+----------------------
+
+.. sidebar:: Installing ``easy_install``
+
+  If you don't already have ``easy_install`` available, you can find the
+  script to set it up on the `PEAK EasyInstall page`_.
+
+  .. _`PEAK EasyInstall page`: http://peak.telecommunity.com/DevCenter/EasyInstall#installing-easy-install
+
+  You need to download `ez_setup.py`_. Then, you run it like this to
+  install ``easy_install`` into your system Python::
+
+    $ sudo python2.4 ez_setup.py
+
+  .. _`ez_setup.py`: http://peak.telecommunity.com/dist/ez_setup.py
+
+  This will make ``easy_install`` available to you.
+
+  **Note**: Sometimes you have ``easy_install`` installed but you need
+  a newer version of the underlying setuptools infrastructure to make
+  Grok work. You can automatically upgrade setuptools this by doing::
+
+    $ sudo easy_install -U setuptools
+
+Setting up grok on a Unix-like (Linux, Mac OS X) environment is
+easy. 
+
+Let's go through the prerequisites first. You need a computer
+connected to the internet, as Grok installs itself over the
+network. You also need Python 2.4 installed.
+
+Because Grok uses a source distribution of Zope 3, you may need to
+install your operating system's Python "dev" package. You also need a
+working C compiler (typically ``gcc``) installed, as we compile bits of
+Zope 3 during setup. Finally, you also need ``easy_install`` installed
+so it becomes easy to install eggs.
+
+Once you are done with the prerequisites, you can install
+grokproject itself::
+
+  $ sudo easy_install grokproject
+
+We're ready to create our first grok project now!
+
+Creating a grok project
+-----------------------
+
+Let's create a first Grok project. A Grok project is a working
+environment for a developer using Grok. In essence, a directory with a
+lot of files and subdirectories in it. Let's create a Grok project
+called Sample::
+
+  $ grokproject Sample
+
+This tells grokproject to create a new subdirectory called ``Sample``
+and set up the project in there. grokproject will automatically
+download and install Zope 3 and Grok into the project area.  If you
+already have Zope 3.3.x installed, you can save some time and tell
+grokproject to reuse that installation:
+
+  $ grokproject --with-zope3=/usr/local/Zope-3.3.1 Sample
+
+grokproject will tell you what it will be creating::
+
+  Selected and implied templates:
+    grokproject#grokproject  A grok project
+
+  Variables:
+    egg:      Sample
+    package:  sample
+    project:  Sample
+
+The "Selected and implied templates" line is something reported by
+Paste, which is the Python project generation software which
+grokproject is using. After this, it reports three names. 
+
+First, it reports the name this project will have if in the project's
+``setup.py``::
+
+    egg:      Sample
+
+Next, it specifies the name of the Python package that you will be
+developing with. The package will be placed under the project's ``src``
+directory::
+
+    package:  sample
+
+Finally, it gives the name of the project directory that it will
+create (under the current directory)::
+
+    project:  Sample
+
+You will be asked a number of questions now. First you need to supply
+the name of the initial module that your package will contain. We'll
+stick with the default ``app.py``::
+ 
+  Enter module (Name of a demo Python module placed into the package) ['app.py']:
+
+After this Grok asks you for an initial username and password for the
+Zope server. We'll use ``grok`` for both::
+
+  Enter user (Name of an initial administrator user): grok
+  Enter passwd (Password for the initial administrator user): grok
+
+Now you have to wait a while as grokproject downloads Grok and
+possibly Zope 3 and sets up the project environment for you.
+
+After all that, Grok, along with a Zope 3 instance, is ready to go. 
+
+Starting up Zope
+----------------
+
+You can go into the ``Sample`` project directory now::
+
+  $ cd Sample
+
+A Zope 3 instance has been installed in the 'parts/instance'
+directory. You can start it (into the foreground) by typing the
+following::
+
+  $ parts/instance/bin/zopectl fg
+
+This will make Zope 3 available on port 8080, and you can log in with
+username ``grok`` and password ``grok``. Assuming you've started up
+Zope on your localhost, you can go to it here:
+
+  http://localhost:8080
+
+This first pops up a login dialog (username: ``grok`` and password:
+``grok``). It will then show a simple Grok admin interface. This
+allows you to install new Grok applications. 
+
+Our sample application (``sample.app.Sample``) will be available for
+adding. Let's try this out.  Go to the Grok admin page:
+
+  http://localhost:8080
+
+and add a Sample application. Give it the name ``test``.
+
+You can now go to the installed application if you click on its link. This
+will bring you to the following URL:
+
+  http://localhost:8080/test
+
+You should see a simple web page with the following text on it::
+
+  Congratulations!
+
+  Your Grok application is up and running. Edit
+  sample/app_templates/index.pt to change this page.
+
+You can shut down Zope 3 at any time by hitting ``CTRL-c``. Shut it
+down now. We will be shutting down and starting up Zope 3 often in
+this tutorial.
+
+Practice restarting Zope now, as you'll end up doing it a lot during
+this tutorial. It's just stopping Zope and starting it again:
+`CTRL-c`` and then ``parts/instance/bin/zopectl fg`` from your Sample
+project directory.
+
+An empty Grok project
+---------------------
+
+.. sidebar:: What about the other directories and files in our project?
+
+  What about the other files and subdirectories in our ``Sample`` project
+  directory? Grokproject sets up the project using a system called
+  `zc.buildout`_. The ``eggs``, ``develop-eggs`` and ``bin``
+  directories are all set up and maintained by zc.buildout. See its
+  documentation for more information about how to use it. The
+  configuration of the project and its dependency is in
+  ``buildout.cfg``. For now, you can avoid these details however.
+
+  .. _`zc.buildout`: http://cheeseshop.python.org/pypi/zc.buildout
+
+Let's take a closer look at what's been created in the Sample project
+directory.
+
+One of the things grokproject created was a ``setup.py`` file. This file
+contains information about your project. This information is used by
+Python distutils and setuptools. You can use the ``setup.py`` file to
+upload your project to the Python Cheeseshop. We will discuss this in
+more detail later in this tutorial. (XXX)
+
+We have already seen the ``parts`` directory. This directory contains
+all software installed by grokproject that is not a simple Python
+library. The only part interesting to us right now is the ``instance``
+directory, which contains the ``zopectl`` script to start up Zope which
+we used before.
+
+The actual code of the project will all be inside the ``src``
+directory. In it is a Python package directory called ``sample`` with
+the ``app.py`` file that grokproject said it would create. Let's look
+at this file:
+
+.. include:: groktut/an_empty_grok_project/src/sample/app.py
+   :literal:
+
+Not very much yet, but enough to make an installable Grok application
+and display its welcome page. We'll go into the details of what this
+means later.
+
+Besides this, there is an empty ``__init__.py`` file to make this
+directory a Python package. 
+
+There is also a directory called ``app_templates``. It contains a single
+template called ``index.pt``:
+
+.. include:: groktut/an_empty_grok_project/src/sample/app_templates/index.pt
+  :literal:
+
+This is the template for your project's welcome page.
+
+What's left is a ``configure.zcml`` file. Unlike in typical Zope 3
+applications, this will only ever contain a single line that registers
+this application with Zope 3. This means we can typically completely
+ignore it, but we'll show it here once for good measure:
+
+.. include:: groktut/an_empty_grok_project/src/sample/configure.zcml
+   :literal:
+
+Showing pages
+=============
+
+Showing web pages is what puts the *web* in "web applications". You
+start doing this with HTML templates, but Grok doesn't stop at
+templates. Most web pages in a web application will contain complex
+presentation logic that is better handled by separate Python code in
+conjunction with templates. This becomes especially important in more
+complex interactions with the user, such as form handling. After
+reading this chapter, you should already be able to write simple web
+applications with Grok.
+
+Publishing a simple web page
+----------------------------
+
+Let's publish a simple static web page. Grok is geared towards web
+applications and therefore not really meant for publishing a large
+number of static (pregenerated) web pages. For that you're better off
+to use a specialized system such as Apache. Nonetheless, in order to
+develop any web application we need to know how to put some simple
+HTML on the web.
+
+As you saw previously, our ``Sample`` application has a stock front
+page, generated by grokproject. Let's change that.
+
+To do this, go to the ``app_templates`` directory in ``src/sample/``.
+This directory contains the templates used for anything defined in the
+``app`` module. Grok knows to associate the directory to the module by
+its name (``<module_name>_templates``).
+
+In this directory we will edit the ``index`` template for our
+``Sample`` application object. To do this, open the ``index.pt`` file
+in a text editor. The ``.pt`` extension indicates that this file is a
+Zope Page Template (ZPT). We're just going to put HTML in it now, but
+this allows us to make page dynamic later on.
+
+Change the ``index.pt`` file to contain the following (very
+simplistic) HTML:
+
+.. include:: groktut/publishing_a_simple_web_page/src/sample/app_templates/index.pt
+  :literal:
+
+Then reload the page:
+
+  http://localhost:8080/test
+
+You should now see the following text::
+
+  Hello world!
+
+Note that you can change templates and see the effects instantly:
+there is no need to restart Zope to see the effect. This is not true
+for changes on the Python level, for instance when you add a
+template. We show an example of this next.
+
+A second view
+-------------
+
+Our view is named ``index``. This in fact means something slightly
+special: it's the default view of our application object. We can also
+access it explicitly by naming the view:
+
+  http://localhost:8080/test/index
+
+If you view that URL in your browser, you should see the same result
+as before. This is the way all other, non-index views are accessed.
+
+Often, your application needs more than one view. A document for
+instance may have an ``index`` view that displays it, but another
+``edit`` view to change its contents.  To create a second view, create
+another template called ``bye.pt`` in ``app_templates``. Make it have
+the following content:
+
+.. include:: groktut/a_second_view/src/sample/app_templates/bye.pt
+  :literal:
+
+Now we need to tell Grok to actually use this template. To do this,
+modify ``src/sample/app.py`` so that it reads like this:
+
+.. include:: groktut/a_second_view/src/sample/app.py
+  :literal:
+
+As you can see, all we did was add a class called ``Bye`` that
+subclasses from ``grok.View``. This indicates to Grok that we want a
+view named ``bye`` for the application, just like the ``Index`` class
+that was already created for us indicates that we want a view named
+``index``. A *view* is a way to view some model, in this case
+installations of our ``Sample`` application. Note that the view name
+in the URL is always going to be lowercase, while the class name
+normally starts with an uppercase letter.
+
+The empty class definition above is enough for Grok to go look in the
+``app_templates`` directory for ``bye.pt``. The rule is that a the
+template should have the same name as the class, but lowercased and
+with the ``.pt`` postfix.
+
+Restart Zope (``CTRL-C, then ``parts/instance/bin/zopectl fg``). You
+can now go to a new web page called ``bye``:
+
+  http://localhost:8080/test/bye
+
+When you load this web page in a browser, you should see the following
+text::
+
+  Bye world!
+
+Making our page dynamic
+-----------------------
+
+Static web pages are not very helpful if we want to make a dynamic web
+application. Let's make a page that shows the result of a very simple
+calculation: ``1 + 1``. 
+
+We will use a Zope Page Templates (ZPT) directive to do this
+calculation inside ``index.pt`` template. Change the ``index.pt`` to
+read like this:
+
+.. include:: groktut/making_our_page_dynamic/src/sample/app_templates/index.pt
+  :literal:
+
+We've used the ``tal:content`` page template directive to replace the
+content between the ``<p>`` and ``</p>`` tags with something else, in
+this case the result of the Python expression ``1 + 1``.
+
+Since restarting Zope is not necessary for changes that are limited to
+the page templates, you can just reload the web page:
+
+  http://localhost:8080/test
+
+You should see the following result::
+
+  2
+
+Looking at the source of the web page shows us this::
+
+  <html>
+  <body>
+  <p>2</p>
+  </body>
+  </html>
+
+As you can see, the content of the ``<p>`` tag was indeed replaced
+with the result of the expression ``1 + 1``.
+
+Static resources for our web page
+---------------------------------
+
+In real-world web pages, we almost never publish a web page that just
+contains bare-bones HTML. We also want to refer to other resources,
+such as images, CSS files or Javascript files. As an example, let's
+add some style to our web page.
+
+To do this, create a new directory called ``static`` in the ``sample``
+package (so, ``src/sample/static``). In it, place a file called
+``style.css`` and put in the following content:
+
+.. include:: groktut/static_resources_for_our_web_page/src/sample/static/style.css
+  :literal:
+
+In order to use it, we also need to refer to it from our
+``index.pt``. Change the content of ``index.pt`` to read like this:
+
+.. include:: groktut/static_resources_for_our_web_page/src/sample/app_templates/index.pt
+  :literal:
+
+Now restart Zope and reload the page:
+
+  http://localhost:8080/test
+
+The web page should now show up with a red background.
+
+You will have noticed we used the ``tal:attributes`` directive in our
+``index.pt`` now. This uses Zope Page Templates to dynamically
+generate the link to our file ``style.css``.
+
+Let's take a look at the source code of the generated web page::
+
+  <html>
+  <link rel="stylesheet" type="text/css"
+        href="http://localhost:8080/test/@@/sample/style.css" />
+  <body>
+  <p>Hello world!</p>
+  </body>
+  </html>
+
+As you can see, the ``tal:attributes`` directive is gone and has been
+replaced with the following URL to the actual stylesheet:
+
+  http://localhost:8080/test/@@/sample/style.css
+
+We will not go into the details of the structure of the URL here, but
+we will note that because it's generated this way, the link to
+``style.css`` will continue to work no matter where you install your
+application (i.e. in a virtual hosting setup).
+
+Pulling in images or javascript is very similar. Just place your image
+files and `.js` files in the ``static`` directory, and create the URL
+to them using ``static/<filename>`` in your page template.
+
+Using view methods
+------------------
+
+.. sidebar:: Unassociated templates
+
+  If you have followed the tutorial so far, you will have an extra
+  template called ``bye.pt`` in your ``app_templates`` directory.
+  Since in the given ``app.py``e we have no more class using it, the
+  ``bye.pt`` template will have become *unassociated**. When you try
+  to restart Zope, grok will be unable to read your application, and
+  Zope will crash with an error message like this::
+
+    GrokError: Found the following unassociated template(s) when
+    grokking 'sample.app': bye.  Define view classes inheriting from
+    grok.View to enable the template(s).
+
+  To resolve this error, simply remove ``bye.pt`` from your
+  ``app_templates`` directory.
+
+ZPT is deliberately limited in what it allows you to do with Python.
+It is good application design practice to use ZPT for fairly simple
+templating purposes only, and to do anything a bit more complicated in
+Python code. Using ZPT with arbitrary Python code is easy: you just
+add methods to your view class and use them from your template.
+
+Let's see how this is done by making a web page that displays the
+current date and time. We will use our Python interpreter to find out
+what works::
+
+  $ python
+  Python 2.4.4
+  Type "help", "copyright", "credits" or "license" for more information.
+  >>> 
+
+We will need Python's ``datetime`` class, so let's import it::
+
+  >>> from datetime import datetime
+
+Note that this statement brings us beyond the capabilities of simple
+ZPT use; it is not allowed to import arbitrary Python modules from
+within a ZPT template; only Python *expressions* (with a result) are
+allowed, not *statements* such as ``from .. import ..``.
+
+Let's get the current date and time::
+
+  >>> now = datetime.now()
+
+This gives us a date time object; something like this::
+
+  >>> now
+  datetime.datetime(2007, 2, 27, 17, 14, 40, 958809)
+
+Not very nice to display on a web page, so let's turn it into a
+prettier string using the formatting capabilities of the ``datetime``
+object::
+
+  >>> now.strftime('%Y-%m-%d %H:%M')
+  '2007-02-27 17:14'
+
+That looks better.
+
+So far nothing new; just Python. We will integrate this code into our
+Grok project now. Go to ``app.py`` and change it to read like this:
+
+.. include:: groktut/using_view_methods/src/sample/app.py
+  :literal:
+
+We've simply added a method to our view that returns a string
+representing the current date and time. Now to get this string in our
+page template. Change ``index.pt`` to read like this:
+
+.. include:: groktut/using_view_methods/src/sample/app_templates/index.pt
+  :literal:
+
+Restart Zope. This is needed as we changed the content of a Python
+file (``app.py``). Now reload our index page to see whether it worked:
+
+  http://localhost:8080/test
+
+You should see a web page with a date and time like this on your
+screen now::
+
+  2007-02-27 17:21
+
+What happened here? When viewing a page, the view class (in this case
+``Index`` is instantiated by Zope. The name ``view`` in the template
+is always made available and is associated with this instance. We then
+simply call the method on it in our template.
+
+There is another way to write the template that is slightly shorter
+and may be easier to read in some cases, using a ZPT path expression::
+
+  <html>
+  <body>
+  <p tal:content="view/current_datetime"></p>
+  </body>
+  </html>
+
+Running this has the same result as before.
+
+Generating HTML from Python
+---------------------------
+
+While usually you will be using templates to generate HTML, sometimes
+you want to generate complicated HTML in Python and then include it in
+an existing web page. For reasons of security against cross-site
+scripting attacks, TAL will automatically escape any HTML into `&gt;`
+and `&lt;`. With the ``structure`` directive, you can tell TAL
+explicitly to not escape HTML this way, so it is passed literally into
+the template. Let's see how this is done. Change ``app.pt`` to read like
+this:
+
+.. include:: groktut/generating_html_from_python/src/sample/app.py
+  :literal:
+
+and then change ``index.pt`` to read like the following:
+
+.. include:: groktut/generating_html_from_python/src/sample/app_templates/index.pt
+  :literal:
+
+Let's take another look at our web page:
+
+  http://localhost:8080/test
+
+You should see the following text (in bold):
+
+  **ME GROK BOLD**
+
+This means the HTML we generated from the ``some_html`` method was
+indeed successfully integrated in our web page.  Without the the
+``structure`` directive, you would've seen the following instead::
+ 
+  <b>ME GROK BOLD</b>
+
+Completely Python-driven views
+------------------------------
+
+.. sidebar:: Setting the content-type
+
+  When generating the complete content of a page yourself, it's often
+  useful to change the content-type of the page to something else than
+  ``text/plain``. Let's change our code to return simple XML and set
+  the content type to ``text/xml``:
+
+  .. include:: groktut/setting_the_content_type/src/sample/app.py
+    :literal:
+
+  All views in Grok have a ``response`` property that you can use to
+  manipulate response headers.
+
+Sometimes it is inconvenient to have to use a template at all. Perhaps
+we are not returning a HTML page at all, for instance. In this case,
+we can use the special ``render`` method on a view.
+
+Modify ``app.py`` so it reads like this:
+
+.. include:: groktut/completely_python_driven_views/src/sample/app.py
+  :literal:
+
+If you were to start up Zope with an ``index.pt`` template still
+inside ``app_templates`` you would get an error::
+
+    GrokError: Multiple possible ways to render view <class
+    'sample.app.Index'>. It has both a 'render' method as well as an
+    associated template.
+
+In the face of ambiguity Grok, like Python, refuses to guess. To
+resolve this error, remove ``index.pt`` from the ``app_templates``
+directory.
+
+Now take another look at our test application:
+
+  http://localhost:8080/test
+
+You should see the following::
+
+  ME GROK NO TEMPLATE
+
+You should see this even when you view the source of the page. When
+looking at the content type of this page, you will see that it is
+``text/plain``.
+
+Doing some calculation before viewing a page
+--------------------------------------------
+
+Instead of calculating some values in a method call from the template,
+it is often more useful to calculate just before the web page's
+template is calculated. This way you are sure that a value is only
+calculated once per view, even if you use it multiple times.
+
+You can do this by defining an ``update`` method on the view class. Modify
+``app.py`` to read like this:
+
+.. include:: groktut/doing_some_calculation_before_viewing_a_page/src/sample/app.py
+  :literal:
+
+This sets a name ``alpha`` on the view just before the template is
+being displayed, so we can use it from the template. You can set as
+many names on ``self`` as you like.
+
+Now we need a template ``index.pt`` that uses ``alpha``:
+
+.. include:: groktut/doing_some_calculation_before_viewing_a_page/src/sample/app_templates/index.pt
+  :literal:
+
+Restart Zope and then let's take another look at our application:
+
+  http://localhost:8080/test
+
+You should see 256, which is indeed 2 raised to the power 8.
+
+Reading URL parameters
+----------------------
+
+When developing a web application, you don't just want to output data,
+but also want to use input. One of the simplest ways for a web
+application to receive input is by retrieving information as a URL
+parameter. Let's devise a web application that can do sums for us. In
+this application, if you enter the following URL into that
+application:
+
+  http://localhost:8080/test?value1=3&value2=5
+
+you should see the sum (8) as the result on the page. 
+
+Modify ``app.py`` to read like this:
+
+.. include:: groktut/reading_url_parameters/src/sample/app.py
+  :literal:
+
+We need an ``index.pt`` that uses ``sum``:
+
+.. include:: groktut/reading_url_parameters/src/sample/app_templates/index.pt
+  :literal:
+
+Restart Zope. Now going to the folllowing URL should display 8:
+
+  http://localhost:8080/test?value1=3&value2=5
+
+Other sums work too, of course:
+
+  http://localhost:8080/test?value1=50&value2=50
+
+What if we don't supply the needed parameters (``value1`` and
+``value2``) to the request? We get an error:
+
+  http://localhost:8080/test
+
+You can look at the window where you started up Zope to see the error
+traceback. This is the relevant complaint::
+
+  TypeError: Missing argument to update(): value1
+
+We can modify our code so it works even without input for either parameter:
+
+.. include:: groktut/reading_url_parameters2/src/sample/app.py
+  :literal:
+
+Restart Zope, and see it can now deal with missing parameters (they
+default to ``0``).
+
+Simple forms
+------------
+
+.. sidebar:: Automatic forms
+
+  Creating forms and converting and validating user input by hand, as
+  shown in this section, can be rather cumbersome. With Grok, you can
+  use Zope 3's *schema* and *formlib* systems to automate this and
+  more. This will be discussed in a later section. XXX
+
+Entering the parameters through URLs is not very pretty. Let's use a
+form for this instead. Change ``index.pt`` to contain a form, like
+this:
+
+.. include:: groktut/simple_forms/src/sample/app_templates/index.pt
+  :literal:
+
+One thing to note here is that we dynamically generate the form's
+``action``. We make the form submit to itself, basically. Grok views
+have a special method called ``url`` that you can use to retrieve the
+URL of the view itself (and other URLs which we'll go into later).
+
+Leave the ``app.py`` as in the previous section, for now. You can now
+go to the web page::
+
+  http://localhost:8080/test
+
+You can submit the form with some values, and see the result displayed
+below.
+
+We still have a few bugs to deal with however. For one, if we don't fill
+in any parameters and submit the form, we get an error like this::
+
+  File "../app.py", line 8, in update
+    self.sum = int(value1) + int(value2)
+  ValueError: invalid literal for int(): 
+
+This is because the parameters were empty strings, which cannot be
+converted to integers. Another thing that is not really pretty is that
+it displays a sum (0) even if we did not enter any data. Let's change
+``app.py`` to take both cases into account:
+
+.. include:: groktut/simple_forms2/src/sample/app.py
+  :literal:
+
+We catch any TypeError and ValueError here so that wrong or missing
+data does not result in a failure. Instead we display the text "No
+sum". If we don't get any error, the conversion to integer was fine,
+and we can display the sum.
+
+Restart Zope and go to the form again to try it out:
+
+  http://localhost:8080/test
+
+Models
+======
+
+Now we know how to show web pages, we need to go into what we are
+actually showing: the models. The models contain the
+display-independent logic of your application. In this chapter we will
+discuss a number of issues surrounding models: how your views connect
+to models, and how you can make sure the data in your models is stored
+safely. As the complexity of our sample applications grows, we will
+also go into a few more issues surrounding form handling.
+
+A view for a model
+------------------
+
+So far, we have only seen views that do the work all by themselves.
+In typical applications this is not the case however - views display
+information that is stored elsewhere. In Grok applications, views work
+for models: subclasses of ``grok.Model`` or ``grok.Container``. For
+the purposes of this discussion, we can treat a ``grok.Container`` as
+another kind of ``grok.Model`` (more about what makes
+``grok.Container`` special later XXX).
+
+Our ``Sample`` class is a ``grok.Container``, so let's use ``Sample``
+to demonstrate the basic principle. Let's modify ``app.py`` so that
+``Sample`` actually makes some data available:
+
+.. include:: groktut/a_view_for_a_model/src/sample/app.py
+  :literal:
+
+In this case, the information (``"This is important information!"``)
+is just hardcoded, but you can imagine information is retrieved from
+somewhere else, such as a relational database or the filesystem.
+
+We now want to display this information in our template ``index.pt``:
+
+.. include:: groktut/a_view_for_a_model/src/sample/app_templates/index.pt
+  :literal:
+
+Restart Zope. When you view the page:
+
+  http://localhost:8080/test
+
+You should now see the following::
+
+  This is important information!
+
+Previously we have seen that you can access methods and attributes on
+the view using the special ``view`` name in a template. Similarly, the
+name ``context`` is also available in each template. ``context``
+allows us to access information on the context object the view is
+displaying. In this case this is an instance of ``Sample``, our
+application object.
+
+Separating the model from the view that displays it is an important
+concept in structuring applications. The view, along with the
+template, is responsible for displaying the information and its user
+interface. The model represents the actual information (or content)
+the application is about, such as documents, blog entries or wiki
+pages. The model should not know anything about the way it is
+displayed.
+
+This way of structuring your applications allows you to change the way
+your model is displayed without modifying the model itself, just
+the way it is viewed.
+
+Let's do that by making the view do something to the information. Change 
+``app.py`` again:
+
+.. include:: groktut/a_view_for_a_model2/src/sample/app.py
+  :literal:
+
+You can see that it is possible to access the context object (an
+instance of ``Sample``) from within the view class, by accessing the
+``context`` attribute. This gets the same object as when we used the
+``context`` name in our template before.
+
+What we do here is reverse the string returned from the
+``information()`` method. You can try it on the Python prompt::
+
+  >>> ''.join(reversed('foo'))
+  'oof'
+
+Now let's modify the ``index.pt`` template so that it uses the
+``reversed_information`` method:
+
+.. include:: groktut/a_view_for_a_model2/src/sample/app_templates/index.pt
+  :literal:
+
+Restart Zope. When you view the page:
+
+  http://localhost:8080/test
+
+You should now see the following:
+
+  The information: This is important information!
+
+  The information, reversed: !noitamrofni tnatropmi si sihT 
+
+Storing data
+------------
+
+So far we have only displayed either hardcoded data, or calculations
+based on end-user input. What if we actually want to *store* some
+information, such as something the user entered? The easiest way to do
+this with Zope is to use the Zope Object Database (ZODB).
+
+The ZODB is a database of Python objects. You can store any Python
+object in it, though you do need to follow a few simple rules (the
+"rules of persistence", which we will go into later). Our ``Sample``
+application object is stored in the object database, so we can store
+some information on it.
+
+Let's create an application that stores a bit of text for us. We will
+use one view to view the text (``index``) and another to edit it
+(``edit``).
+
+Modify ``app.py`` to read like this:
+
+.. include:: groktut/storing_data/src/sample/app.py
+  :literal:
+
+The ``Sample`` class gained a class attribute with some default text.
+In the ``update`` method of the ``Edit`` view you can see we actually
+set the ``text`` attribute on the context, if at least a ``text``
+value was supplied by a form. This will set the ``text`` attribute on
+the instance of the ``Sample`` object in the object database, and thus
+will override the default ``text`` class attribute.
+
+Change the ``index.pt`` template to read like this:
+
+.. include:: groktut/storing_data/src/sample/app_templates/index.pt
+  :literal:
+
+This is a very simple template that just displays the ``text``
+attribute of the ``context`` object (our ``Sample`` instance).
+
+Create an ``edit.pt`` template with the following content:
+
+.. include:: groktut/storing_data/src/sample/app_templates/edit.pt
+  :literal:
+
+This template display a form asking for a bit of text. It submits to
+itself.
+
+Restart Zope. Let's first view the index page:
+
+  http://localhost:8080/test
+
+You should see ``default text``.
+
+Now let's modify the text by doing to the edit page of the application:
+
+  http://localhost:8080/test/edit
+
+Type in some text and press the "Store" button. Since it submits to
+itself, we will see the form again, so go to the index page manually:
+
+  http://localhost:8080/test
+ 
+You should now see the text you just entered on the page. This means
+that your text was successfully stored in the object database!
+
+You can even restart Zope and go back to the index page, and your text
+should still be there.
+
+Redirection
+-----------
+
+Let's make our application a bit easier to use. First, let's change
+``index.pt`` so it includes a link to the edit page. To do this, we
+will use the ``url`` method on the view:
+
+.. include:: groktut/redirection/src/sample/app_templates/index.pt
+  :literal:
+
+Giving ``url`` a single string argument will generate a URL to the
+view named that way on the same object (``test``), so in this case
+``test/edit``.
+
+Now let's change the edit form so that it redirects back to the
+``index`` page after you press the submit button:
+
+.. include:: groktut/redirection/src/sample/app.py
+  :literal:
+
+The last line is the new one. We use the ``url`` method on the view to
+construct a URL to the ``index`` page. Since we're in the template, we
+can simply call ``url`` on ``self``. Then, we pass this to another
+special method available on all ``grok.View`` subclasses,
+``redirect``. We tell the system to redirect to the ``index`` page.
+
+Showing the value in the form
+-----------------------------
+
+Let's change our application so it displays what we stored the edit
+form as well, not just on the index page.
+
+To make this work, change edit.pt so it reads like this:
+
+.. include:: groktut/showing_the_value_in_the_form/src/sample/app_templates/edit.pt
+  :literal:
+
+The only change is that we have used ``tal:attributes`` to include the
+value of the ``text`` attribute of the context object in the form.
+
+The rules of persistence
+------------------------
+
+These are the "rules of persistence":
+
+* You should subclass classes that want to store data from
+  ``persistent.Persistent`` so that it's easy to store them in the
+  ZODB. The simplest way to do this with Grok is to subclass from
+  ``grok.Model`` or ``grok.Container``.
+
+* Instances that you want to store should be connected to other
+  persistent classes that are already stored. The simplest way to do
+  this with Grok is to attach them somehow to the ``grok.Application``
+  object, directly or indirectly. This can be done by setting them as
+  an attribute, or by putting them in a container (if you made your
+  application subclass ``grok.Container``).
+
+* To make sure that the ZODB knows you changed a mutable attribute
+  (such as a simple Python list or dictionary) in your instance, set
+  the special ``_p_changed`` attribute on that instance to
+  ``True``. This is only necessary if that attribute is not
+  ``Persistent`` itself. It is also not necessary when you create or
+  overwrite an attribute directly using ``=``.
+
+If you construct your application's content out of ``grok.Model`` and
+``grok.Container`` subclasses you mostly follow the rules
+already. Just remember to set ``_p_changed`` in your methods if you
+find yourself modifying a Python list (with ``append``, for instance)
+or dictionary (by storing a value in it).
+
+The code in the section `Storing data`_ is a simple example. We in
+fact have to do nothing special at all to obey the rules of
+persistence in that case.
+
+If we use a mutable object such as a list or dictionary to store data
+instead, we do need to take special action. Let's change our example
+code (based on the last section) to use a mutable object (a list):
+
+.. include:: groktut/the_rules_of_persistence/src/sample/app.py
+  :literal:
+
+We have now changed the ``Sample`` class to do something new: it has
+an ``__init__`` method. Whenever you create the ``Sample`` application
+object now, it will be created with an attribute called ``list``,
+which will contain an empty Python list. 
+
+We also make sure that the ``__init__`` method of the superclass still
+gets executed, by using the regular Python ``super`` idiom. If we
+didn't do that, our container would not be fully initialized.
+
+You will also notice a small change to the ``update`` method of the
+``Edit`` class. Instead of just storing the text as an attribute of
+our ``Sample`` model, we add each text we enter to the new
+``list`` attribute on. 
+
+Note that this code has a subtle bug in it, which is why we've added
+the comment. We will see what bug this is in a little bit. First,
+though, let's change our templates.
+
+We change ``index.pt`` so that it displays the list:
+
+.. include:: groktut/the_rules_of_persistence/src/sample/app_templates/index.pt
+  :literal:
+
+We've also changed the text of the link to the ``edit`` page to reflect
+the new adding behavior of our application.
+
+We need to undo the change to the ``edit.pt`` template that we
+made in the last section, as each time we edit a text we now *add* a
+new text, instead of changing the original. There is therefore no text
+to show in as the input value anymore:
+
+.. include:: groktut/the_rules_of_persistence/src/sample/app_templates/edit.pt
+  :literal:
+
+.. sidebar:: evolution
+
+  What to do when you change an object's storage structure while your
+  application is already in production? In a later section, we will
+  introduce Zope 3's object evolution mechanism that allows you to
+  update objects in an existing object database. XXX
+
+Let's restart our Zope application. If you have followed the tutorial
+from the last section, you will now see an error when you look at the
+front page of the application::
+
+  A system error occurred. 
+
+Look at the output Zope gave when we tried to load our page::
+
+  AttributeError: 'Sample' object has no attribute 'list'
+
+But we just changed our object to have an attribute ``list``, right?
+Yes we did, but only for *new* instances of the Sample object. What we
+are looking at is the sample object from before, still stored in the
+object database. It has no such attribute. This isn't a bug by the way
+(for our actual bug, see later in this section): it is just a database
+problem.
+
+What to do now? The simplest action to take during development is to
+simply remove our previously installed application, and create a new
+one that *does* have this attribute. Go to the Grok admin screen:
+
+  http://localhost:8080
+
+Select the application object (``test``) and delete it. Now install it
+again, as ``test``. Now go to its edit screen and add a text:
+
+  http://localhost:8080/test/edit
+
+Click on ``add a text`` and add another text. You will see the new
+texts appear on the ``index`` page.
+
+Everything is just fine now, right? In fact, not so! Now we will get
+to our bug. Restart Zope and look at the index page again:
+
+  http://localhost:8080/test
+
+None of the texts we added were saved! What happened? We broke the
+third rule of persistence as described above: we modified a mutable
+attribute and did not notify the database that we made this
+change. This means that the object database was not aware of our
+change to the object in memory, and thus never saved it to disk.
+
+.. sidebar: The ZODB only stores instance data
+
+  Note that the ZODB only stores ("persists") instance data. This
+  means that any data you have directly associated with a class, as
+  opposed to the instance, won't be persisted. Normally you only
+  associate immutable data with the class, so this is not a problem::
+ 
+    class Foo(object):
+        mydata = 'some text'
+
+  That data will be there when the module is imported, and since it 
+  will never be changed, there isn't a problem. Now let's check what
+  happens with mutable data::
+
+    class Foo(object):
+        mydata = []
+
+  Appending an item to mydata (through ``self.mydata.append('bar')``,
+  for instance) have an effect, but only until you restart Zope. Then
+  your changes will be lost.
+
+  It is good Python design practice not to use mutable class-data, so
+  this property of the ZODB shouldn't cramp your style.
+ 
+We can easily amend this by adding one line to the code:
+
+.. include:: groktut/the_rules_of_persistence2/src/sample/app.py
+  :literal:
+
+We've now told Zope that the context object has changed (because we
+modified a mutable sub-object), by adding the line::
+
+  self.context._p_changed = True
+
+If you now add some texts and then restart Zope, you will notice the
+data is still there: it has successfully been stored in the object
+database.
+
+The code shown so far is a bit ugly in the sense that typically we
+would want to manage our state in the model code (the ``Sample``
+object in this case), and not in the view. Let's make one final
+change to show what that would look like:
+
+.. include:: groktut/the_rules_of_persistence3/src/sample/app.py
+  :literal:
+
+As you can see, we have created a method ``addText`` to the model that
+takes care of amending the list and informing the ZODB about it. This
+way, any view code can safely use the API of ``Sample`` without having
+to worry about the rules of persistence itself, as that is the model's
+responsibility.
+
+Explicitly associating a view with a model
+------------------------------------------
+
+How does Grok know that a view belongs to a model? In the previous
+examples, Grok has made this association automatically. Grok could do
+this because there was only a single model defined in the module
+(``Sample``). In this case, Grok is clever enough to automatically
+associate all views defined elsewhere in the same module to the only
+model. Behind the scenes Grok made the model the *context* of the
+views.
+
+Everything that Grok does implicitly you can also tell Grok to do
+explicitly. This will come in handy later, as you may sometimes need
+(or want) to tell Grok what to do, overriding its default behavior. To
+associate a view with a model automatically, you use the
+``grok.context`` class annotation.
+
+What is a class annotation? A class annotation is a declarative way
+to tell grok something about a Python class. Let's look at an example.
+We will change ``app.py`` in the example from `A second view` to demonstrate
+the use of ``grok.context``:
+
+.. include:: groktut/explicitly_associating_a_view_with_a_model/src/sample/app.py
+  :literal:
+
+This code behaves in exactly the same way as the previous example in
+`A second view`, but has the relationship between the model and the
+view made explicit, using the ``grok.context`` class annotation.
+
+``grok.context`` is just one class annotation out of many. We will see
+another one (``grok.name``) in the next section.
+
+A second model
+--------------
+
+.. sidebar:: How to combine models into a single application?
+
+  Curious now about how to combine models into a single application?
+  Can't wait? Look at the section `Containers` coming up next, or
+  `Traversal` later on.
+
+We will now extend our application with a second model. Since we
+haven't explained yet how to combine models together into a single
+application, we will just create a second application next to our
+first one. Normally we probably wouldn't want to define two
+applications in the same module, but we are trying to illustrate a few
+points, so please bear with us. Change ``app.py`` so it looks like
+this:
+
+.. include:: groktut/a_second_model/src/sample/app.py
+  :literal:
+
+You can see we now defined a second application class, ``Another``.
+It subclasses from ``grok.Application`` to make it an installable
+application.  
+
+It also subclasses from ``grok.Model``. There is a difference between
+``grok.Model`` and ``grok.Container``, but for the purpose of the
+discussion we can ignore it for now. We just figured we should use
+``grok.Model`` for some variety, though we could have indeed
+subclassed from ``grok.Container`` instead.
+
+We also define two templates, one called ``sampleindex.pt``:
+
+.. include:: groktut/a_second_model/src/sample/app_templates/sampleindex.pt
+  :literal:
+
+And one called ``anotherindex.pt``:
+
+.. include:: groktut/a_second_model/src/sample/app_templates/anotherindex.pt
+  :literal:
+
+We have named the templates the name as the lowercased class names as
+the views, so that they get associated with them.
+
+You will have noticed we have used ``grok.context`` to associate the
+views with models. We actually *have* to do this here, as Grok refuses
+to guess in the face of ambiguity. Without the use of
+``grok.context``, we would have seen an error like this when we start
+up Zope::
+
+  GrokError: Multiple possible contexts for <class
+  'sample.app.AnotherIndex'>, please use grok.context.
+
+So, we use ``grok.context`` to explicitly associate ``SampleIndex``
+with the ``Sample`` application, and again to associate
+``AnotherIndex`` with the ``Another`` application.
+
+We have another problem: the intent is for these views to be ``index``
+views. This cannot be deduced automatically from the name of the view
+classes however, and left to its own devices, Grok would have called
+the views ``sampleindex`` and ``anotherindex``. 
+
+Luckily we have another class annotation that can help us here:
+``grok.name``. We can use it on both view classes
+(``grok.name('index')``) to explicitly explain to Grok what we want.
+
+You can now try to restart Zope and create both applications. They
+should display the correct index pages when you look at them.
+
+We can see that the introduction of a second model has complicated our
+code a bit, though you will hopefully agree with us that it is still
+quite readable. We could have avoided the whole problem by simply
+placing ``Another`` and its views in another module such as
+``another.py``.  Its associated templates would then need to be placed
+in a directory ``another_templates``. Often you will find it possible
+to structure your application so you can use Grok's default
+conventions.
+
+Containers 
+----------
+
+A container is a special kind of model object that can contain other
+objects. Our ``Sample`` application is already a container, as it
+subclasses ``grok.Container``. What we will do in this section is
+build an application that actually puts something into that container.
+
+Grok applications ar typically composed of containers and
+models. Containers are objects that can contain models. This includes
+other containers, as a container is just a special kind of model.
+
+From the perspective of Python, you can think of containers as
+dictionaries.  They allow item access (``container['key']``) to get at
+its contents. They also define methods such as ``keys()`` and
+``values()``. Containers do a lot more than Python dictionaries
+though: they are persistent, and when you modify them, you don't have
+to use `_p_changed` anywhere to notice you changed them. They also
+send out special events that you can listen to when items are placed
+in them or removed from them. For more on that, see the section on
+events (XXX).
+
+Our application object will have a single index page that displays the
+list of items in the container. You can click an item in the list to
+view that item. Below the list, it will display a form that allows you
+to create new items.
+
+Here is the ``app.py`` of our new application:
+
+.. include:: groktut/containers/src/sample/app.py
+  :literal:
+
+As you can see, ``Sample`` is unchanged. We have also created our
+first non-application object, ``Entry``. It is just a
+``grok.Model``. It needs to be created with an argument ``text`` and
+this text is stored in it. We intend to place instances of ``Entry``
+in our ``Sample`` container.
+
+Next are the views. We have an ``index`` page for the ``Sample``
+container. When its ``update()`` is triggered with two values,
+``name`` and ``text``, it will create a new ``Entry`` instance with
+the given text, and place it under the container under the name
+``name``. We use the dictionary-like interface of our ``Sample``
+container to put our new ``Entry`` in the container.
+
+Here is the associated template for ``SampleIndex``, ``sampleindex.pt``:
+
+.. include:: groktut/containers/src/sample/app_templates/sampleindex.pt
+  :literal:
+
+The first section in the template (``<h2>Existing entries</h2>``)
+displays a list of the items in the container. We again use
+dictionary-like access using ``keys()`` to get a list of all the names
+of the items in the container. We create a link to these items using
+``view.url()``.
+
+The next section (``<h2>Add a new entry</h2>``) displays a simple form
+that submits to the index page itself. It has two fields, ``name`` and
+``text``, which we already have seen handled by ``update()``.
+
+Finally, we have an ``index`` page for ``Entry``. It just has a template
+to display the ``text`` attribute:
+
+.. include:: groktut/containers/src/sample/app_templates/entryindex.pt
+  :literal:
+
+Restart Zope and try this application.  Call your application
+``test``. Pay special attention to the URLs.
+
+First, we have the index page of our application:
+
+  http://localhost:8080/test
+
+When we create an entry called ``hello`` in the form, and then click on it
+in the list, you see an URL that looks like this:
+
+  http://localhost:8080/test/hello
+
+We are now looking at the index page of the instance of ``Entry``
+called ``hello``.
+
+What kind of extensions to this application can we think of? We could
+create an ``edit`` form that allows you to edit the text of
+entries. We could modify our application so that you can not just add
+instances of ``Entry``, but also other containers. If you made those
+modifications, you would be on your way to building your own content
+management system with Grok.


Property changes on: grok/branches/darrylcousins-martian-layers/doc/tutorial.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/doc/tutorial_outline.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/doc/tutorial_outline.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/doc/tutorial_outline.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,236 @@
+================
+Tutorial outline
+================
+
+This is not the tutorial itself, but a sketch of what the tutorial
+could look like. This hopefully inspires people to contribute to the
+tutorial. The structure of the tutorial is very much use-case driven
+and about getting things done. This means we tend to discuss the
+component architecture itself very late.
+
+Note that while I've indicated the overal aim of sections in chapters,
+that doesn't mean a chapter is absolutely decicated to a single
+topic. If for instance in the course of explaining search it becomes
+important to override traversal, it can be discussed right there.
+
+Main tutorial
+=============
+
+Getting started with Grok
+-------------------------
+
+This section aims to get a beginner up and running with Grok, using
+grokproject. It doesn't really go into any code yet, except to
+describe what grokproject creates.
+
+  * Setting up grokproject
+
+  * Creating a grok project
+
+  * Starting up Zope
+
+  * An empty Grok project
+
+Showing pages
+-------------
+
+We get beginners up to speed with writing view logic in Grok. This is
+basically the first thing beginners want - just get some HTML on the
+screen. Basic templating, supplementing templating with view-level
+methods, and various basic interaction patterns. Models are still out
+of scope. Armed with this knowledge people should already be able to
+write simple web applications with Grok, if at least they don't have
+to worry much about storing data.
+
+  * Publishing a simple web page
+
+  * A second view
+
+  * Making our page dynamic
+
+  * Static resources for our web page
+
+  * Using view methods
+
+  * Generating HTML from Python
+
+  * Completely Python-driven views
+
+  * Doing some calculation before viewing a page
+
+  * Reading URL parameters
+
+  * Simple forms
+
+Models
+------
+
+Once we know how to show things, we need to go into what we're
+actually showing: the model. This involves view/model separation,
+dealing with the ZODB and persistence, and constructing applications
+from models and containers. 
+
+Note that we also include some more advanced view use cases which only
+tend to become relevant with more complicated applications (such as
+redirection).
+
+  * A view for a model
+ 
+  * Storing data
+ 
+  * Redirection
+
+  * Showing the value in the form
+
+  * The rules of persistence
+ 
+  * Containers
+
+Some notes:
+
+* What if a container already contains an item with the same name? We will
+  get an error. How to handle this error elegantly?
+
+Forms
+-----
+
+Now that we've seen the form and storage basics, we go a step further
+and show the power of automatic form generation from schemas.
+
+Building on the patterns we've seen before, we develop a simple CRUD
+application with an overview screen and add and edit forms. This will
+also include at least a glance at interfaces in the context of
+schemas.
+
+Search
+------
+
+We have a way for a user to enter information. Now we need to build an
+application that does something with it. We extend our CRUD
+application with indexing and search, using the catalog.
+
+By now the application should also be advanced enough to explain
+overriding traversal, for instance to enable simple 'tag' based
+browsing mechanism based on search. We need to show a pattern where
+non-persistent objects are created in traversal.
+
+This will also lead into a brief introduction of utility lookup and
+sites.
+
+XXX setting up the catalog is easy now, but it can be automated a bit
+    further still in Grok.
+
+XXX We probably need hurry.query. This needs some work on the Grok end
+    to expose this nicely.
+
+Custom widgets
+--------------
+
+The defaults are never enough when it comes to web forms. This is a
+nice point to introduce making your own custom form widgets.
+
+We will also show how you can use AJAX with Grok so you can give your
+widget some dynamic behavior.
+
+XXX we need to make it easy to make widgets in Grok.
+
+XXX this needs work on the Grok end to at least expose JSON, and perhaps
+     we need to ship with a 'recommended' Javascript library.
+
+Security
+--------
+
+Explain how Grok allows you to protect your views. In the course of
+this we also need to explain a bit about Zope 3's user authentication
+system, as we need users to test this with.
+
+XXX We need to flesh out user authentication issues in Grok.
+
+Extending our application
+-------------------------
+
+We show one of Zope 3's main strengths: we create a separate codebase
+in a completely separate project that extends the first. Then we
+demonstrate many extension patterns Zope 3 offers:
+
+  * creating an extension project (using buildout and SVN externals?)
+
+  * a new look for old models (skins)
+
+  * the benefit of interfaces
+
+  * events
+
+  * adapters
+
+Appendices
+==========
+
+While these topics may not presuppose a lot of knowledge, we probably
+do not want to scatter all of this through the tutorial itself so as
+not to distract from the main story (though we may change our minds if
+it seems to come out naturally).
+
+Explicit configuration
+----------------------
+
+Should give an introduction on the principles of Grok: explicit
+configuration using directives, with defaults so you can leave them
+off if you follow the grok patterns.
+
+I'm not sure yet whether this can be part of the main flow of the
+text. We at the very least will refer to this at some point in the
+text though, and we need to refer people to this for more information.
+
+The Component Architecture
+--------------------------
+
+Explain how many bits and pieces we've seen so far are actually
+aspects of the component architecture.
+
+Automatic testing
+-----------------
+
+A brief introduction to automatic testing. Introduce how to unit test
+and functional test with doctests.
+
+XXX We probably need to do some development work on a test grokker.
+
+XMLRPC 
+------
+
+Show how to do XMLRPC with Grok.
+
+Extending grok
+--------------
+
+Grok can be extended using Grokkers. Explain how to do it here.
+
+Development issues
+------------------
+
+We describe best practices on how to manage your code when developing
+with Grok. This touches topics like setup.py, buildout, and also
+version control systems.
+
+ * Pulling in new dependencies from the Cheeseshop.
+
+ * Putting your project into SVN
+
+ * Uploading your project to the Python Cheeseshop
+
+Items I'm not sure where to place yet
+=====================================
+
+These items will need to find a place in the main narrative or the
+appendices. They're listed here so we don't forget about them:
+
+  * Constructing urls with view.url()
+
+  * base classes
+
+  * Events
+
+  * Showing error pages.
+
+  * Discussion on viewlets/portlets.


Property changes on: grok/branches/darrylcousins-martian-layers/doc/tutorial_outline.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/ftesting.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/ftesting.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/ftesting.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,89 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:meta="http://namespaces.zope.org/meta"
+   i18n_domain="zope"
+   >
+
+  <!-- This file is the equivalent of site.zcml and it is -->
+  <!-- used for functional testing setup -->
+
+  <!-- zope dependency includes -->
+  <include package="zope.app.securitypolicy" file="meta.zcml" />
+  <include package="zope.i18n" file="meta.zcml" />
+  <include package="zope.security" file="meta.zcml" />
+  <include package="zope.app.zcmlfiles" />
+  <include package="zope.app.securitypolicy" file="configure.zcml" />
+  <include package="zope.contentprovider" />
+  <include package="zope.formlib" />
+  <include package="zope.i18n.locales" />
+  <include package="zope.traversing.browser" />
+  <include package="zope.app.authentication" />
+  <include package="zope.app.catalog" />
+  <include package="zope.app.intid" />
+  <include package="zope.app.keyreference" />
+  <include package="zope.app.twisted" />
+  <include package="zope.app.session" />
+  <include package="zope.viewlet" />
+
+  <include package="zope.app.zcmlfiles" file="ftesting.zcml" />
+
+  <!-- my friend the caveman -->
+  <include package="grok" file="meta.zcml" />
+  <include package="grok" file="configure.zcml" />
+
+  <securityPolicy
+    component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
+
+  <role id="zope.Anonymous" title="Everybody"
+                 description="All users have this role implicitly" />
+  <role id="zope.Manager" title="Site Manager" />
+  <role id="zope.Member" title="Site Member" />
+
+  <include package="zope.app.securitypolicy.tests" file="functional.zcml" />
+
+  <!-- Principals -->
+
+  <unauthenticatedPrincipal
+      id="zope.anybody"
+      title="Unauthenticated User" />
+
+  <unauthenticatedGroup
+    id="zope.Anybody"
+    title="Unauthenticated Users"
+    />
+
+  <authenticatedGroup
+    id="zope.Authenticated"
+    title="Authenticated Users"
+    />
+
+  <everybodyGroup
+    id="zope.Everybody"
+    title="All Users"
+    />
+
+  <!-- Principal that tests generally run as -->
+  <principal
+      id="zope.mgr"
+      title="Manager"
+      login="mgr"
+      password="mgrpw" />
+
+  <!-- Bootstrap principal used to make local grant to the principal above -->
+  <principal
+      id="zope.globalmgr"
+      title="Manager"
+      login="globalmgr"
+      password="globalmgrpw" />
+
+  <grant role="zope.Manager" principal="zope.globalmgr" />
+
+  <!-- Replace the following directive if you don't want public access -->
+  <grant permission="zope.View"
+                  role="zope.Anonymous" />
+  <grant permission="zope.app.dublincore.view"
+                  role="zope.Anonymous" />
+
+  <grantAll role="zope.Manager" />
+
+</configure>

Added: grok/branches/darrylcousins-martian-layers/grokblog/README.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/grokblog/README.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/grokblog/README.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+grokblog is now... Grokstar! 
+
+http://svn.zope.org/Grokstar


Property changes on: grok/branches/darrylcousins-martian-layers/grokblog/README.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/grokwiki/README.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/grokwiki/README.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/grokwiki/README.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+=============
+The grok wiki
+=============
+
+The grok wiki is our first demo application, used to demonstrate how grok can
+be used to efficiently write web applications with Zope 3.
+
+It is not so much intended as a tutorial, but as a test bed for ourselves and
+to provide guidance for new users how we are using grok ourselves.


Property changes on: grok/branches/darrylcousins-martian-layers/grokwiki/README.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/grokwiki/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/grokwiki/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/grokwiki/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+from setuptools import setup, find_packages
+
+setup(
+    name='grokwiki',
+    version='0.1',
+    author='Grok Team',
+    author_email='grok-dev at zope.org',
+    url='http://svn.zope.org/grok/trunk',
+    description="""\
+Grok: Now even cavemen can use wikis!
+""",
+    packages=find_packages('src'),
+    package_dir = {'': 'src'},
+    include_package_data = True,
+    zip_safe=False,
+    license='ZPL',
+
+    install_requires=['setuptools',
+                     ],
+)


Property changes on: grok/branches/darrylcousins-martian-layers/grokwiki/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+<grok package="." xmlns="http://namespaces.zope.org/grok" />
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,58 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""The grok demo wiki
+"""
+import re
+import grok
+
+
+LINK_PATTERN = re.compile('\[\[(.*?)\]\]')
+find_wiki_links = LINK_PATTERN.findall
+
+
+class WikiPage(grok.Model):
+
+    def __init__(self):
+        self.text = u"GROK EMPTY WIKI PAGE. FILL!"
+
+    def update(self, text):
+        links = find_wiki_links(text)
+        for link in links:
+            if link not in self.__parent__:
+                self.__parent__[link] = WikiPage()
+        self.text = text
+
+
+class Layout(grok.View):
+    pass
+
+
+class Index(grok.View):
+
+    def update(self):
+        wiki_url = self.url(self.context.__parent__)
+        self.rendered_text, replacements = (
+            LINK_PATTERN.subn(r'<a href="%s/\1">\1</a>' % wiki_url, 
+                              self.context.text))
+
+class Edit(grok.View):
+
+    def update(self):
+        text = self.request.form.get('wikidata')
+        if not text:
+            return # Just render the template
+
+        # Update the text and redirect
+        self.context.update(text)
+        self.redirect(self.url(self.context))


Property changes on: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/edit.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/edit.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/edit.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,10 @@
+<html metal:use-macro="context/@@layout/main">
+    <div metal:fill-slot="content">
+        <h1>Edit &raquo;<span tal:replace="context/__name__">WikiPage</span>&laquo;</h1>
+
+        <form tal:attributes="action view/url" method="POST">
+        <textarea name="wikidata" tal:content="context/text" cols="80" rows="20"/><br/>
+        <input type="submit" value="Update"/>
+        </form>
+    </div>
+</html>

Added: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,10 @@
+<html metal:use-macro="context/@@layout/main">
+    <div metal:fill-slot="content">
+        <h1 tal:content="context/__name__">WikiPage</h1>
+
+        <div tal:content="structure view/rendered_text" class="wikicontent">
+        </div>
+
+        <p><a tal:attributes="href python:view.url('edit')">Edit this page</a></p>
+    </div>
+</html>

Added: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/layout.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/layout.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/page_templates/layout.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,26 @@
+<html metal:define-macro="main">
+    <head>
+        <link rel="stylesheet" tal:attributes="href static/wiki.css" type="text/css">
+    </head>
+
+    <body
+        tal:define="wiki context/__parent__">
+        <div metal:define-slot="content">
+            Page content goes here ...
+        </div>
+
+        <hr/>
+        <h3>Other pages</h3>
+        <p>
+            <span tal:repeat="page wiki">
+                <a tal:attributes="href python:view.url(wiki, page)"
+                   tal:content="page"
+                   />
+            </span>
+        </p>
+        <hr/>
+        <div id="footer">
+        This Wiki was grokked by Zope 3.
+        </div>
+    </body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/static/wiki.css
===================================================================
--- grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/static/wiki.css	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/static/wiki.css	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,15 @@
+body {
+    font-family: Helvetica, Arial, sans;
+}
+
+.wikicontent {
+    margin:1em;
+    background-color:#EEEEEE;
+    border:1px solid #999999;
+    padding:1em;
+}
+
+#footer {
+    font-size:70%;
+    color:#999999;
+}

Added: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/wiki.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/wiki.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/wiki.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""The grok demo wiki
+"""
+
+import grok
+import grokwiki.page
+
+class Wiki(grok.Application, grok.Container):
+    """This is our wiki application wich contains all wiki pages."""
+
+class Index(grok.View):
+    def render(self):
+        self.redirect(self.url('home'))
+
+ at grok.subscribe(Wiki, grok.IObjectAddedEvent)
+def setupHomepage(wiki, event):
+    """Creates a home page for every wiki."""
+    page = grokwiki.page.WikiPage()
+    wiki['home'] = page


Property changes on: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/wiki.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/xmlrpc.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/xmlrpc.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/xmlrpc.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""XML/RPC access to the wiki pages
+"""
+
+import grok
+import grokwiki.page
+
+
+class WikiPageRPC(grok.XMLRPC):
+    grok.context(grokwiki.page.WikiPage)
+
+    def edit(self, text):
+        self.context.update(text)
+
+    def show(self):
+        return self.context.text


Property changes on: grok/branches/darrylcousins-martian-layers/grokwiki/src/grokwiki/xmlrpc.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/ldapaddressbook/README.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/ldapaddressbook/README.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/ldapaddressbook/README.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,26 @@
+=================
+LDAP address book
+=================
+
+A grok example application that shows how to load and store objects from
+external data sources.
+
+
+Dependencies
+------------
+
+  - Requires python-ldap (no egg available yet)
+
+
+Issues
+------
+
+  - grok.EditForm gives no chance to perform a single update with the data of
+    all forms
+
+  - Container (AddressBook) has to set __parent__ and __name__ for the
+    dynamically created contacts 
+
+  - Mapping outside schemata to inside schema is tedious
+
+  - formlib acquires standard ZMI layout


Property changes on: grok/branches/darrylcousins-martian-layers/ldapaddressbook/README.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/ldapaddressbook/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/ldapaddressbook/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/ldapaddressbook/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+from setuptools import setup, find_packages
+
+setup(
+    name='ldapaddressbook',
+    version='0.1',
+    author='Christian Theune',
+    author_email='ct at gocept.com',
+    url='http://svn.zope.org/repos/main/grok/trunk/',
+    description="""\
+Allows to edit addressbook entries of ~inetOrgPerson in LDAP
+""",
+    packages=find_packages('src'),
+    package_dir = {'': 'src'},
+    include_package_data = True,
+    zip_safe=False,
+    license='ZPL',
+
+    install_requires=['setuptools',
+                     ],
+)


Property changes on: grok/branches/darrylcousins-martian-layers/ldapaddressbook/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/addressbook.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/addressbook.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/addressbook.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,179 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""The grok LDAP address book.
+"""
+
+import ldap
+
+
+
+from zope import schema
+
+import grok
+
+
+LDAP_SERVER = "ldap://ldaphost:389"
+LDAP_LOGIN = "cn=admin,dc=example,dc=com"
+LDAP_PASSWORD = "password"
+LDAP_SEARCH_BASE = "ou=Addresses,dc=example,dc=com"
+
+
+
+class AddressBook(grok.Application):
+
+    def traverse(self, name):
+        contact = Contact(name)
+        contact.__parent__ = self
+        contact.__name__ = name
+        return contact
+
+    def listContacts(self):
+        return get_contact_list()
+
+
+class AddressBookListing(grok.View):
+    grok.context(AddressBook)
+    grok.name("index")
+
+
+addressbooklisting = grok.PageTemplate("""\
+<html>
+<body>
+<ul>
+    <li tal:repeat="contact context/listContacts">
+        <a tal:attributes="href string:${context/@@absolute_url}/$contact" tal:content="contact">Peter Kummer</a></li>
+</ul>
+</body>
+</html>""")
+
+
+class Contact(grok.Model):
+
+    class fields:
+        cn = schema.TextLine(title=u"LDAP CN", readonly=True)
+
+        givenName = schema.TextLine(title=u"First name", required=False)
+        sn = schema.TextLine(title=u"Last name")
+        initials = schema.TextLine(title=u"Initials", required=False)
+
+        # jpegPhoto
+        description = schema.TextLine(title=u"Description", required=False)
+
+        title = schema.TextLine(title=u"Title", required=False)
+
+        o = schema.TextLine(title=u"Organisation", required=False)
+        ou = schema.TextLine(title=u"Organisational Unit", required=False)
+        businessRole = schema.TextLine(title=u"Role", required=False)
+
+        category = schema.TextLine(title=u"Category", required=False)
+
+        mail = schema.List(title=u"Email", required=False,
+                value_type=schema.TextLine())
+
+        telephoneNumber = schema.TextLine(title=u"Phone (business)", required=False)
+        mobile = schema.TextLine(title=u"Mobiltelefon", required=False)
+        facsimileTelephoneNumber = schema.TextLine(title=u"Telefax (business)", required=False)
+        homePhone = schema.TextLine(title=u"Phone (private)", required=False)
+
+        note = schema.TextLine(title=u"Note", required=False)
+
+        postalAddress = schema.Text(title=u"Address (business)", required=False)
+        postalCode = schema.TextLine(title=u"ZIP", required=False)
+        street = schema.TextLine(title=u"Street", required=False)
+        l = schema.TextLine(title=u"City", required=False)
+        st = schema.TextLine(title=u"State", required=False)
+
+        homePostalAddress = schema.Text(title=u"Address (private)", required=False)
+
+        labeledURI = schema.TextLine(title=u"Homepage", required=False)
+
+    def __init__(self, cn):
+        # Initialize from LDAP data
+        data = get_contact(cn)
+        if data is not None:
+            for field in grok.schema_fields(Contact):
+                field_data = data.get(field.__name__)
+                if not field_data:
+                    continue
+                if isinstance(field, schema.TextLine):
+                    setattr(self, field.__name__, field_data[0])
+                elif isinstance(field, schema.Text):
+                    setattr(self, field.__name__, '\n'.join(field_data))
+                elif isinstance(field, schema.List):
+                    setattr(self, field.__name__, field_data)
+                else:
+                    raise TypeError, "Invalid schema field type: %r" % field
+
+    def update(self, data):
+        for key, value in data.items():
+            setattr(self, key, value)
+        store_contact(self)
+
+
+class EditContact(grok.EditForm):
+    grok.context(Contact)
+    grok.name("index")
+
+    @grok.action("Apply")
+    def apply(self, action, data):
+        # XXX UI feedback and modification event triggering
+        self.context.update(data)
+
+
+# LDAP helper functions
+
+def get_contact_list():
+    l = ldap.initialize(LDAP_SERVER)
+    l.simple_bind_s(LDAP_LOGIN, LDAP_PASSWORD)
+    results = l.search_s(LDAP_SEARCH_BASE, ldap.SCOPE_SUBTREE, "(objectclass=inetOrgPerson)")
+    import pprint
+    pprint.pprint(results)
+    if results is None:
+        return []
+    cns = [unicode(x[1]['cn'][0], 'utf-8') for x in results]
+    cns.sort()
+    return cns
+
+def get_contact(cn):
+    l = ldap.initialize(LDAP_SERVER)
+    l.simple_bind_s(LDAP_LOGIN, LDAP_PASSWORD)
+    results = l.search_s(LDAP_SEARCH_BASE,
+                         ldap.SCOPE_SUBTREE,
+                         "(&(objectclass=inetOrgPerson)(cn=%s))" % cn)
+    if results:
+        # Get data dictionary
+        data = results[0][1] 
+        for key, value in data.items():
+            value = [unicode(v, 'utf-8') for v in value]
+            data[key] = value
+        return data
+
+def store_contact(contact):
+    l = ldap.initialize(LDAP_SERVER)
+    l.simple_bind_s(LDAP_LOGIN, LDAP_PASSWORD)
+    dn = "cn=%s,%s" % (contact.cn.encode('utf-8'), LDAP_SEARCH_BASE)
+
+    modlist = []
+    for field in  grok.schema_fields(contact):
+        value = field.get(contact)
+        if value is None:
+            value  = []
+        elif isinstance(field, schema.Text):
+            value = value.split("\n")
+        elif not isinstance(value, list):
+            value = [value]
+        value = map(lambda x:x.encode('utf-8'), value)
+
+        modlist.append((ldap.MOD_REPLACE, field.__name__, value))
+    l.modify_s(dn, modlist)


Property changes on: grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/addressbook.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/ldapaddressbook/src/ldapaddressbook/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,15 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    xmlns:grok="http://namespaces.zope.org/grok"
+    i18n_domain="grok"
+    >
+    <grok:grok package="."/>
+
+    <browser:addMenuItem
+        class=".addressbook.AddressBook"
+        title="LDAP Addressbook"
+        description="LDAP Addressbook"
+        permission="zope.ManageContent"
+        />
+</configure>

Added: grok/branches/darrylcousins-martian-layers/martian/CREDITS.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/CREDITS.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/CREDITS.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,17 @@
+CREDITS
+=======
+
+* Martijn Faassen
+ 
+* Wolfgang Schnerring
+
+* Christian Theune
+
+* Philipp von Weitershausen
+
+* Jan-Wijbrand Kolman
+
+Thank you
+---------
+
+* The core Grok developers.


Property changes on: grok/branches/darrylcousins-martian-layers/martian/CREDITS.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/martian/LICENSE.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/LICENSE.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/LICENSE.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,54 @@
+Zope Public License (ZPL) Version 2.1
+-------------------------------------
+
+A copyright notice accompanies this license document that
+identifies the copyright holders.
+
+This license has been certified as open source. It has also
+been designated as GPL compatible by the Free Software
+Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the
+following conditions are met:
+
+1. Redistributions in source code must retain the
+   accompanying copyright notice, this list of conditions,
+   and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the accompanying
+   copyright notice, this list of conditions, and the
+   following disclaimer in the documentation and/or other
+   materials provided with the distribution.
+
+3. Names of the copyright holders must not be used to
+   endorse or promote products derived from this software
+   without prior written permission from the copyright
+   holders.
+
+4. The right to distribute this software or to use it for
+   any purpose does not give you the right to use
+   Servicemarks (sm) or Trademarks (tm) of the copyright
+   holders. Use of them is covered by separate agreement
+   with the copyright holders.
+
+5. If any files are modified, you must cause the modified
+   files to carry prominent notices stating that you changed
+   the files and the date of any change.
+
+Disclaimer
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS''
+  AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
+  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+  NO EVENT SHALL THE COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+  DAMAGE.


Property changes on: grok/branches/darrylcousins-martian-layers/martian/LICENSE.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/martian/README.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/README.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/README.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,43 @@
+Martian
+=======
+
+"There was so much to grok, so little to grok from." -- Stranger in a
+Strange Land, by Robert A. Heinlein
+
+Martian provides infrastructure for declarative configuration of
+Python code. Martian is especially useful for the construction of
+frameworks that need to provide a flexible plugin infrastructure. 
+
+Why is this package named ``martian``? In the novel "Stranger in a
+Strange Land", the verb *grok* is introduced:
+
+  Grok means to understand so thoroughly that the observer becomes a
+  part of the observed -- to merge, blend, intermarry, lose identity
+  in group experience.
+
+In the context of this package, "grokking" stands for the process of
+deducing declarative configuration actions from Python code. In the
+novel, grokking is originally a concept that comes from the planet
+Mars. Martians *grok*. Since this package helps you grok code, it's
+called Martian.
+
+Martian provides a framework that allows configuration to be expressed
+in declarative Python code. These declarations can often be decuded
+from the structure of the code itself. The idea is to make these
+declarations so minimal and easy to read that even extensive
+configuration does not overly burden the programmers working with the
+code. Configuration actions are executed during a separate phase
+("grok time"), not at import time, which makes it easier to reason
+about and easier to test.
+
+The ``martian`` package is a spin-off from the `Grok project`_, in the
+context of which this codebase was first developed. While Grok uses
+it, the code is completely independent of Grok.
+
+For more information about using Martian, see:
+
+  src/martian/README.txt
+  src/martian/directive.txt
+  src/martian/scan.txt
+
+.. _`Grok project`: http://grok.zope.org


Property changes on: grok/branches/darrylcousins-martian-layers/martian/README.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/martian/bootstrap.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/bootstrap.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/bootstrap.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,55 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id$
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+try:
+    import pkg_resources
+except ImportError:
+    ez = {}
+    exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                         ).read() in ez
+    ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)


Property changes on: grok/branches/darrylcousins-martian-layers/martian/bootstrap.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/buildout.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/buildout.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/buildout.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,12 @@
+[buildout]
+develop = . 
+parts = devpython test
+
+[devpython]
+recipe = zc.recipe.egg
+interpreter = devpython
+eggs = martian
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = martian

Added: grok/branches/darrylcousins-martian-layers/martian/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,24 @@
+from setuptools import setup, find_packages
+
+setup(
+    name='martian',
+    version='0.1',
+    author='Grok project',
+    author_email='grok-dev at zope.org',
+    description="""\
+Martian is a library that allows the embedding of configuration
+information in Python code. Martian can then grok the system and
+do the appropriate configuration registrations. One example of a system
+that uses Martian is the system where it originated: Grok
+(http://grok.zope.org)
+""",
+    packages=find_packages('src'),
+    package_dir = {'': 'src'},
+    include_package_data = True,
+    zip_safe=False,
+    license='ZPL',
+    install_requires=[
+    'zope.interface',
+    'setuptools',
+    ],
+)


Property changes on: grok/branches/darrylcousins-martian-layers/martian/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/README.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/README.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/README.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,1118 @@
+Martian
+=======
+
+"There was so much to grok, so little to grok from." -- Stranger in a
+Strange Land, by Robert A. Heinlein
+
+Martian provides infrastructure for declarative configuration of
+Python code. Martian is especially useful for the construction of
+frameworks that need to provide a flexible plugin infrastructure. 
+
+Why is this package named ``martian``? In the novel "Stranger in a
+Strange Land", the verb *grok* is introduced:
+
+  Grok means to understand so thoroughly that the observer becomes a
+  part of the observed -- to merge, blend, intermarry, lose identity
+  in group experience.
+
+In the context of this package, "grokking" stands for the process of
+deducing declarative configuration actions from Python code. In the
+novel, grokking is originally a concept that comes from the planet
+Mars. Martians *grok*. Since this package helps you grok code, it's
+called Martian.
+
+The ``martian`` package is a spin-off from the `Grok project`_, in the
+context of which this codebase was first developed. While Grok uses
+it, the code is completely independent of Grok.
+
+.. _`Grok project`: http://grok.zope.org
+
+Motivation
+----------
+
+"Deducing declarative configuration actions from Python code" - that
+sounds very abstract. What does it actually mean? In order to explain
+this, let's first look at an example of a simple framework that can be
+*configured* with plugins. We will define a framework for handling
+files based on their extensions::
+
+  >>> class filehandler(FakeModule):
+  ...   import os
+  ...
+  ...   def handle_txt(filepath):
+  ...     return "Text file"
+  ...
+  ...   def handle_xml(filepath):
+  ...     return "XML file"
+  ...
+  ...   extension_handlers = { '.txt': handle_txt, '.xml': handle_xml }
+  ...
+  ...   def handle(filepath):
+  ...      name, ext = os.path.splitext(filepath)
+  ...      return extension_handlers[ext](filepath)
+
+Since normally we cannot create modules in a doctest, we have emulated
+the ``filehandler`` Python module using the ``FakeModule``
+class. Whenever you see ``FakeModule`` subclasses, imagine you're
+looking at a module definition in a ``.py`` file. Now that we have
+defined a module ``filehandler, we also need to be able to import
+it. To do so we can use a a fake import statement that lets us do
+this::
+
+  >>> filehandler = fake_import(filehandler)
+
+Now let's try the ``handle`` function for a few file types::
+
+  >>> filehandler.handle('test.txt')
+  'Text file'
+  >>> filehandler.handle('test2.xml')
+  'XML file'
+
+File extensions that we do not recognize cause a ``KeyError`` to be
+raisedr::
+ 
+  >>> filehandler.handle('image.png')  
+  Traceback (most recent call last):
+  ...
+  KeyError: '.png'
+
+We now want to plug into this filehandler framework and provide the a
+handler for ``.png`` files. Since we are writing a plugin, we cannot
+change the ``filehandler`` module directly. Let's write an extension
+module instead::
+
+  >>> class pnghandler(FakeModule):
+  ...    def handle_png(filepath):
+  ...        return "PNG file"
+  ...
+  ...    filehandler.extension_handlers['.png'] = handle_png
+  >>> pnghandler = fake_import(pnghandler)
+
+In the extension module, we manipulate the ``extension_handlers``
+dictionary of the ``filehandler`` module and plug in our own
+function. PNG handling works now::
+
+  >>> filehandler.handle('image.png')
+  'PNG file'
+
+The action of registering something into a central registry is also
+called *configuration*. Larger frameworks often offer a lot of points
+where you can configure them: ways to combine its own components with
+components you provide yourself to build a larger application. 
+
+Above we plug into our ``extension_handler`` registry using Python
+code. Using separate code to manually hook components into registries
+can get rather cumbersome - each time you write an extension, you also
+need to remember you need to register it. It also poses a maintenance
+risk. It is tempting to start doing fancy things in Python code such
+as conditional configuration, making the configuration state of a
+program hard to understand. Another problem is that doing
+configuration at import time can also lead to unwanted side effects
+during import and ordering problems. It can also make code harder to
+test.
+
+Martian provides a framework that allows configuration to be expressed
+in declarative Python code. These declarations can often be decuded
+from the structure of the code itself. The idea is to make these
+declarations so minimal and easy to read that even extensive
+configuration does not overly burden the programmers working with the
+code. Configuration actions are executed during a separate phase
+("grok time"), not at import time, which makes it easier to reason
+about and easier to test.
+
+Grokkers that grok
+------------------
+
+In this section we define the concept of a ``Grokker``. A ``Grokker``
+is an object that can *grok* objects - execute configuration actions
+pertaining to the grokked object, such as registering it with some
+central registry. Different kinds of grokkers can grok different types
+of objects (instances, classes, functions).
+
+Let's define a Grokker to help us register the file type handler
+functions as seen in our previous example::
+
+  >>> import types
+  >>> from zope.interface import implements
+  >>> from martian import InstanceGrokker
+  >>> class FileTypeGrokker(InstanceGrokker):
+  ...   component_class = types.FunctionType 
+  ...
+  ...   def grok(self, name, obj, **kw):
+  ...     if not name.startswith('handle_'):
+  ...       return False
+  ...     ext = name.split('_')[1]
+  ...     filehandler.extension_handlers['.' + ext] = obj
+  ...     return True
+
+This ``InstanceGrokker`` allows us to grok instances of a particular
+type (such as functions). We need to define the type of object we're
+looking for with the ``component_class`` attribute. In the ``grok``
+method, we first make sure we only grok functions that have a name
+that starts with ``handle_``. Then we determine the used extension
+from the name and register the funcion in the ``extension_handlers``
+dictionary of the ``filehandler`` module. We return ``True`` if we
+indeed grokked the object.
+
+An instance will provide the IGrokker interface::
+
+  >>> filetype_grokker = FileTypeGrokker()
+  >>> from martian.interfaces import IGrokker
+  >>> IGrokker.providedBy(filetype_grokker)
+  True
+
+Now let's use the grokker to grok a new handle function::
+
+  >>> def handle_jpg(filepath):
+  ...   return "JPG file"
+  >>> filetype_grokker.grok('handle_jpg', handle_jpg)
+  True
+
+After we grokked, we have have registered a handler for ``.jpg`` files
+(the extension to register under was deduced from the function name)::
+ 
+  >>> sorted(filehandler.extension_handlers.keys())
+  ['.jpg', '.png', '.txt', '.xml']
+
+This means now our ``filehandler.handle`` function is now able to
+handle JPG files as well::
+  
+  >>> filehandler.handle('image2.jpg')
+  'JPG file'
+
+If we try to grok a function that doesn't start with ``handle_`` in its
+name, nothing will happen::
+
+  >>> def something(filepath):
+  ...   return 'Something'
+  >>> filetype_grokker.grok('something', something)
+  False
+  >>> 'something' in filehandler.extension_handlers
+  False
+
+Grokking a module
+-----------------
+
+Grokking individual components is useful, but to make Martian really
+useful we need to be able to grok whole modules or packages as well.
+Let's look at a special grokker that can grok a Python module::
+
+  >>> from martian import ModuleGrokker
+
+The idea is that the ``ModuleGrokker`` groks any components in a
+module that it recognizes. A ``ModuleGrokker`` does not work alone. It
+needs to be supplied with one or more grokkers that can grok the
+components to be founded in a module::
+
+  >>> module_grokker = ModuleGrokker()
+  >>> module_grokker.register(filetype_grokker)
+
+We now define a module that defines a few filetype handlers to be
+grokked::
+
+  >>> class lotsofhandlers(FakeModule):
+  ...   def handle_exe(filepath):
+  ...     return "EXE file"
+  ...
+  ...   def handle_ogg(filepath):
+  ...     return "OGG file"
+  ...
+  ...   def handle_svg(filepath):
+  ...     return "SVG file"
+  >>> lotsofhandlers = fake_import(lotsofhandlers)
+
+Let's grok it::
+
+  >>> module_grokker.grok('lotsofhandlers', lotsofhandlers)
+  True
+
+The new registrations are now available::
+
+  >>> sorted(filehandler.extension_handlers.keys())
+  ['.exe', '.jpg', '.ogg', '.png', '.svg', '.txt', '.xml']
+
+The system indeed recognizes them now::
+
+  >>> filehandler.handle('test.ogg')
+  'OGG file'
+  >>> filehandler.handle('test.svg')
+  'SVG file'
+  >>> filehandler.handle('test.exe')
+  'EXE file'
+
+As you can see, with Martian we can now define handlers without ever
+having to register them manually. This allows us to rewrite our
+original module and take out the manual registrations completely::
+
+  >>> class filehandler(FakeModule):
+  ...   import os
+  ...
+  ...   def handle_txt(filepath):
+  ...     return "Text file"
+  ...
+  ...   def handle_xml(filepath):
+  ...     return "XML file"
+  ...
+  ...   extension_handlers = {}
+  ...
+  ...   def handle(filepath):
+  ...      name, ext = os.path.splitext(filepath)
+  ...      return extension_handlers[ext](filepath)
+
+  >>> filehandler = fake_import(filehandler)
+ 
+Let's use martian to do the registrations for us::
+
+  >>> module_grokker.grok('filehandler', filehandler)
+  True
+  >>> filehandler.handle('test.txt')
+  'Text file'
+
+InstanceGrokker
+---------------
+
+We have seen how to grok module-level functions. Let's now grok some
+other kind of instance, a ``Color``::
+
+  >>> class color(FakeModule):
+  ...   class Color(object):
+  ...     def __init__(self, r, g, b):
+  ...       self.r = r
+  ...       self.g = g
+  ...       self.b = b
+  ...     def __repr__(self):
+  ...       return '<Color %s %s %s>' % (self.r, self.g, self.b) 
+  ...   all_colors = {}
+  >>> color = fake_import(color)
+
+We now want a grokker that can recognize colors and put them in the
+``all_colors`` dictionary, with the names as the keys, and the color
+object as the values. We can use ``InstanceGrokker`` to construct it::
+
+  >>> class ColorGrokker(InstanceGrokker):
+  ...   component_class = color.Color
+  ...   def grok(self, name, obj):
+  ...     color.all_colors[name] = obj
+  ...     return True
+
+Let's create ``color_grokker`` and grok a color::
+
+  >>> color_grokker = ColorGrokker()
+  >>> black = color.Color(0, 0, 0) # we DO consider black as a color :)
+  >>> color_grokker.grok('black', black)
+  True
+
+It ends up in the ``all_colors`` dictionary::
+
+  >>> color.all_colors
+  {'black': <Color 0 0 0>}
+
+If we put ``color_grokker`` into a ``ModuleGrokker``, we can now grok
+multiple colors in a module::
+
+  >>> Color = color.Color
+  >>> class colors(FakeModule):
+  ...   red = Color(255, 0, 0)
+  ...   green = Color(0, 255, 0)
+  ...   blue = Color(0, 0, 255)
+  ...   white = Color(255, 255, 255)
+  >>> colors = fake_import(colors)
+  >>> colors_grokker = ModuleGrokker() 
+  >>> colors_grokker.register(color_grokker)
+  >>> colors_grokker.grok('colors', colors)
+  True
+  >>> sorted(color.all_colors.items())
+  [('black', <Color 0 0 0>), 
+   ('blue', <Color 0 0 255>), 
+   ('green', <Color 0 255 0>), 
+   ('red', <Color 255 0 0>), 
+   ('white', <Color 255 255 255>)]
+
+Subclasses of ``Color`` are also grokked::
+
+  >>> class subcolors(FakeModule):
+  ...   class SpecialColor(Color):
+  ...     pass
+  ...   octarine = SpecialColor(-255, 0, -255)
+  >>> subcolors = fake_import(subcolors)
+  >>> colors_grokker.grok('subcolors', subcolors)
+  True
+  >>> 'octarine' in color.all_colors
+  True
+
+MultiInstanceGrokker
+--------------------
+
+In the previous section we have created a particular grokker that
+looks for instances of a component class, in this case
+``Color``. Let's introduce another ``InstanceGrokker`` that looks for
+instances of ``Sound``::
+  
+  >>> class sound(FakeModule):
+  ...   class Sound(object):
+  ...     def __init__(self, desc):
+  ...       self.desc = desc
+  ...     def __repr__(self):
+  ...       return '<Sound %s>' % (self.desc) 
+  ...   all_sounds = {}
+  >>> sound = fake_import(sound)
+
+  >>> class SoundGrokker(InstanceGrokker):
+  ...   component_class = sound.Sound
+  ...   def grok(self, name, obj):
+  ...     sound.all_sounds[name] = obj
+  ...     return True
+  >>> sound_grokker = SoundGrokker()
+ 
+What if we now want to look for ``Sound`` and ``Color`` instances at
+the same time? We have to use the ``color_grokker`` and
+``sound_grokker`` at the same time, and we can do this with a
+``MultiInstanceGrokker``::
+
+  >>> from martian.core import MultiInstanceGrokker
+  >>> multi_grokker = MultiInstanceGrokker()
+  >>> multi_grokker.register(color_grokker)
+  >>> multi_grokker.register(sound_grokker)
+
+Let's grok a new color with our ``multi_grokker``::
+
+  >>> grey = Color(100, 100, 100)
+  >>> multi_grokker.grok('grey', grey)
+  True
+  >>> 'grey' in color.all_colors
+  True
+
+Let's grok a sound with our ``multi_grokker``::
+  
+  >>> moo = sound.Sound('Moo!')
+  >>> multi_grokker.grok('moo', moo)
+  True
+  >>> 'moo' in sound.all_sounds
+  True
+
+We can also grok other objects, but this will have no effect::
+
+  >>> something_else = object()
+  >>> multi_grokker.grok('something_else', something_else)
+  False
+
+Let's put our ``multi_grokker`` in a ``ModuleGrokker``. We can do
+this by passing it explicitly to the ``ModuleGrokker`` factory::
+
+  >>> module_grokker = ModuleGrokker(grokker=multi_grokker)
+
+We can now grok a module for both ``Color`` and ``Sound`` instances::
+
+  >>> Sound = sound.Sound
+  >>> class lightandsound(FakeModule):
+  ...   dark_red = Color(150, 0, 0)
+  ...   scream = Sound('scream')
+  ...   dark_green = Color(0, 150, 0)
+  ...   cheer = Sound('cheer')
+  >>> lightandsound = fake_import(lightandsound)
+  >>> module_grokker.grok('lightandsound', lightandsound)
+  True
+  >>> 'dark_red' in color.all_colors
+  True
+  >>> 'dark_green' in color.all_colors
+  True
+  >>> 'scream' in sound.all_sounds
+  True
+  >>> 'cheer' in sound.all_sounds
+  True
+
+ClassGrokker
+------------
+
+Besides instances we can also grok classes. Let's define an application
+where we register classes representing animals::
+
+  >>> class animal(FakeModule):
+  ...   class Animal(object):
+  ...     name = None
+  ...     def __repr__(self):
+  ...       return '<Animal %s>' % self.name
+  ...   all_animals = {}
+  ...   def create_animal(name):
+  ...     return all_animals[name]() 
+  >>> animal = fake_import(animal)
+  
+Let's define a grokker that can grok an ``Animal``::
+
+  >>> from martian import ClassGrokker
+  >>> class AnimalGrokker(ClassGrokker):
+  ...   component_class = animal.Animal
+  ...   def grok(self, name, obj, **kw):
+  ...     animal.all_animals[obj.name] = obj
+  ...     return True
+
+Let's test our grokker::
+
+  >>> animal_grokker = AnimalGrokker()
+  >>> class Snake(animal.Animal):
+  ...   name = 'snake'
+  >>> animal_grokker.grok('snake', Snake)
+  True
+  >>> animal.all_animals.keys()
+  ['snake']
+
+We can create a snake now::
+
+  >>> animal.create_animal('snake')
+  <Animal snake>
+
+MultiClassGrokker
+-----------------
+
+We now want to be able to grok the following module and have the
+``Animal`` subclasses (but not the ``Chair`` class, which is not an
+animal) automatically become available::
+
+  >>> class animals(FakeModule):
+  ...   class Elephant(animal.Animal):
+  ...     name = 'elephant'
+  ...   class Tiger(animal.Animal):
+  ...     name = 'tiger'
+  ...   class Lion(animal.Animal):
+  ...     name = 'lion'
+  ...   class Chair(object):
+  ...     name = 'chair'
+  >>> animals = fake_import(animals)
+
+First we need to wrap our ``AnimalGrokker`` into a ``MultiClassGrokker``::
+
+ >>> from martian.core import MultiClassGrokker
+ >>> multi_grokker = MultiClassGrokker()
+ >>> multi_grokker.register(animal_grokker)
+
+Now let's wrap it into a ``ModuleGrokker`` and grok the module::
+
+  >>> grokker = ModuleGrokker(grokker=multi_grokker)
+  >>> grokker.grok('animals', animals)
+  True
+
+The animals (but not anything else) should have become available::
+
+  >>> sorted(animal.all_animals.keys())
+  ['elephant', 'lion', 'snake', 'tiger']
+
+We can create animals using their name now::
+
+  >>> animal.create_animal('elephant')
+  <Animal elephant>
+  >>> animal.create_animal('tiger')
+  <Animal tiger>
+
+MultiGrokker
+------------
+
+``MultiInstanceGrokker`` and ``MultiClassGrokker`` can grok instances
+and classes respectively, but a ``MultiInstanceGrokker`` won't work
+correctly if it runs into a class and vice versa. For that we use a
+``MultiGrokker``, which can deal with the full range of objects that
+can be grokked, and skips those it doesn't recognize.
+
+Let's fill a ``MultiGrokker`` with a bunch of grokkers::
+
+  >>> from martian import MultiGrokker
+  >>> multi = MultiGrokker()
+  >>> multi.register(filetype_grokker)
+  >>> multi.register(color_grokker)
+  >>> multi.register(sound_grokker)
+  >>> multi.register(animal_grokker)
+
+Let's try it with some individual objects::
+
+  >>> class Whale(animal.Animal):
+  ...    name = 'whale'
+  >>> multi.grok('Whale', Whale)
+  True
+  >>> 'whale' in animal.all_animals
+  True
+ 
+This should have no effect, but not fail::
+
+  >>> my_whale = Whale()
+  >>> multi.grok('my_whale', my_whale)
+  False
+
+Grokked by the ColorGrokker::
+
+  >>> multi.grok('dark_grey', Color(50, 50, 50))
+  True
+  >>> 'dark_grey' in color.all_colors 
+  True
+
+Grokked by the SoundGrokker::
+  
+  >>> multi.grok('music', Sound('music'))
+  True
+  >>> 'music' in sound.all_sounds
+  True
+
+Not grokked::
+
+  >>> class RockMusic(Sound):
+  ...   pass
+  >>> multi.grok('RockMusic', RockMusic)
+  False
+
+Grokked by SoundGrokker::
+
+  >>> multi.grok('rocknroll', RockMusic('rock n roll'))
+  True
+  >>> 'rocknroll' in sound.all_sounds
+  True
+
+Not grokked::
+
+  >>> class Chair(object):
+  ...   pass
+  >>> multi.grok('Chair', Chair)
+  False
+
+Grokked by ``filetype_grokker``::
+
+  >>> def handle_py(filepath):
+  ...   return "Python file"
+  >>> multi.grok('handle_py', handle_py)
+  True
+  >>> '.py' in filehandler.extension_handlers
+  True
+
+Not grokked:
+
+  >>> def foo():
+  ...   pass
+  >>> multi.grok('foo', foo)
+  False
+
+Not grokked either::
+  
+  >>> another = object()
+  >>> multi.grok('another', another)
+  False
+  
+Let's make a module which has a mixture between classes and instances,
+some of which can be grokked::
+
+  >>> class mix(FakeModule):
+  ...   # grokked by AnimalGrokker
+  ...   class Whale(animal.Animal):
+  ...      name = 'whale'
+  ...   # not grokked
+  ...   my_whale = Whale()
+  ...   # grokked by ColorGrokker
+  ...   dark_grey = Color(50, 50, 50)
+  ...   # grokked by SoundGrokker
+  ...   music = Sound('music')
+  ...   # not grokked
+  ...   class RockMusic(Sound):
+  ...      pass
+  ...   # grokked by SoundGrokker
+  ...   rocknroll = RockMusic('rock n roll')
+  ...   # grokked by AnimalGrokker
+  ...   class Dragon(animal.Animal):
+  ...     name = 'dragon'
+  ...   # not grokked
+  ...   class Chair(object):
+  ...     pass
+  ...   # grokked by filetype_grokker
+  ...   def handle_py(filepath):
+  ...     return "Python file"
+  ...   # not grokked
+  ...   def foo():
+  ...     pass
+  ...   # grokked by AnimalGrokker
+  ...   class SpermWhale(Whale):
+  ...     name = 'sperm whale'
+  ...   # not grokked
+  ...   another = object()
+  >>> mix = fake_import(mix)
+
+Let's construct a ``ModuleGrokker`` that can grok this module::
+
+  >>> mix_grokker = ModuleGrokker(grokker=multi)
+
+Note that this is actually equivalent to calling ``ModuleGrokker``
+without arguments and then calling ``register`` for the individual
+``ClassGrokker`` and ``InstanceGrokker`` objects.
+
+Before we do the grokking, let's clean up our registration
+dictionaries::
+
+  >>> filehandler.extension_handlers = {}
+  >>> color.all_colors = {} 
+  >>> sound.all_sounds = {}
+  >>> animal.all_animals = {}
+
+Now we grok::
+
+  >>> mix_grokker.grok('mix', mix)
+  True
+  >>> sorted(filehandler.extension_handlers.keys())
+  ['.py']
+  >>> sorted(color.all_colors.keys())
+  ['dark_grey']
+  >>> sorted(sound.all_sounds.keys())
+  ['music', 'rocknroll']
+  >>> sorted(animal.all_animals.keys())
+  ['dragon', 'sperm whale', 'whale']
+
+GlobalGrokker
+-------------
+
+Sometimes you want to let a grok action happen for each module. The
+grok action could for instance read the globals of a module, or even
+static files associated with the module by name. Let's create a module
+with some global value::
+
+  >>> class g(FakeModule):
+  ...   amount = 50
+  >>> g = fake_import(g)
+ 
+Now let's create a ``GlobalGrokker`` that reads ``amount`` and stores
+it in the ``read_amount`` dictionary::
+
+  >>> read_amount = {}
+  >>> from martian import GlobalGrokker
+  >>> class AmountGrokker(GlobalGrokker):
+  ...   def grok(self, name, module):
+  ...     read_amount[None] = module.amount
+  ...     return True
+
+Let's construct a ``ModuleGrokker`` with this ``GlobalGrokker`` registered::
+
+  >>> grokker = ModuleGrokker()
+  >>> grokker.register(AmountGrokker())
+
+Now we grok and should pick up the right value::
+
+  >>> grokker.grok('g', g)
+  True
+  >>> read_amount[None]
+  50 
+
+Old-style class support
+-----------------------
+
+So far we have only grokked either new-style classes or instances of
+new-style classes. It is also possible to grok old-style classes and
+their instances::
+
+  >>> class oldstyle(FakeModule):
+  ...   class Machine:
+  ...     pass
+  ...   all_machines = {}
+  ...   all_machine_instances = {}
+  >>> oldstyle = fake_import(oldstyle)
+
+Let's make a grokker for the old style class::
+
+  >>> class MachineGrokker(ClassGrokker):
+  ...   component_class = oldstyle.Machine
+  ...   def grok(self, name, obj):
+  ...     oldstyle.all_machines[name] = obj
+  ...     return True
+
+And another grokker for old style instances::
+
+  >>> class MachineInstanceGrokker(InstanceGrokker):
+  ...   component_class = oldstyle.Machine
+  ...   def grok(self, name, obj):
+  ...     oldstyle.all_machine_instances[name] = obj
+  ...     return True
+
+The multi grokker should succesfully grok the old-style ``Machine`` class
+and instances of it::
+
+  >>> multi = MultiGrokker()
+  >>> multi.register(MachineGrokker())
+  >>> multi.register(MachineInstanceGrokker())
+  >>> class Robot(oldstyle.Machine):
+  ...   pass
+  >>> multi.grok('Robot', Robot)
+  True
+  >>> oldstyle.all_machines.keys()
+  ['Robot']
+  >>> robot = Robot()
+  >>> multi.grok('robot', robot)
+  True
+  >>> oldstyle.all_machine_instances.keys()
+  ['robot']
+
+Grokking a package
+------------------
+
+A package consists of several sub modules. When grokking a package,
+all the files in the package will be grokked. Let's first create a simple
+grokker for the ``Animal`` class defined by the package::
+
+  >>> from martian.tests.testpackage import animal
+  >>> all_animals = {}
+  >>> class AnimalGrokker(ClassGrokker):
+  ...   component_class = animal.Animal
+  ...   def grok(self, name, obj, **kw):
+  ...     all_animals[name] = obj
+  ...     return True
+
+The grokker will collect animals into the ``all_animals`` dictionary.
+
+Let's register this grokker for a ModuleGrokker::
+
+  >>> module_grokker = ModuleGrokker()
+  >>> module_grokker.register(AnimalGrokker())
+
+Now let's grok the whole ``testpackage`` for animals::
+
+  >>> from martian import grok_dotted_name
+  >>> grok_dotted_name('martian.tests.testpackage', grokker=module_grokker)
+  
+We should now get some animals::
+
+  >>> sorted(all_animals.keys())
+  ['Animal', 'Bear', 'Dragon', 'Lizard', 'Python', 'SpermWhale', 'Whale']
+
+Preparation and finalization
+----------------------------
+
+Before grokking a module, it may be that we need to do some
+preparation. This preparation can include setting up some parameters
+to pass along to the grokking process, for instance. We can pass
+a ``prepare`` function a the ModuleGrokker::
+
+  >>> class Number(object):
+  ...   def __init__(self, nr):
+  ...     self.nr = nr
+  >>> all_numbers = {}
+  >>> class NumberGrokker(InstanceGrokker):
+  ...  component_class = Number
+  ...  def grok(self, name, obj, multiplier):
+  ...    all_numbers[obj.nr] = obj.nr * multiplier
+  ...    return True
+  >>> def prepare(name, module, kw):
+  ...   kw['multiplier'] = 3
+  >>> module_grokker = ModuleGrokker(prepare=prepare)
+  >>> module_grokker.register(NumberGrokker())
+ 
+We have created a ``prepare`` function that does one thing: create a
+``multiplier`` parameter that is passed along the grokking
+process. The ``NumberGrokker`` makes use of this to prepare the
+``all_numbers`` dictionary values.
+
+Let's try this with a module::
+
+  >>> class numbers(FakeModule):
+  ...   one = Number(1)
+  ...   two = Number(2)
+  ...   four = Number(4)
+  >>> numbers = fake_import(numbers)
+  >>> module_grokker.grok('numbers', numbers)
+  True
+  >>> sorted(all_numbers.items())
+  [(1, 3), (2, 6), (4, 12)]
+
+You can also optionally register a finalization function, which will
+be run at the end of a module grok::
+
+  >>> def finalize(name, module, kw):
+  ...     all_numbers['finalized'] = True
+  >>> module_grokker = ModuleGrokker(prepare=prepare, finalize=finalize)
+  >>> module_grokker.register(NumberGrokker())
+  >>> all_numbers = {}
+  >>> module_grokker.grok('numbers', numbers)
+  True
+  >>> 'finalized' in all_numbers
+  True
+
+Sanity checking
+---------------
+
+Grokkers must return ``True`` if grokking succeeded, or ``False`` if
+it didn't. If they return something else (typically ``None`` as the
+programmer forgot to), the system will raise an error::
+
+  >>> class BrokenGrokker(InstanceGrokker):
+  ...  component_class = Number
+  ...  def grok(self, name, obj):
+  ...    pass
+
+  >>> module_grokker = ModuleGrokker()
+  >>> module_grokker.register(BrokenGrokker())
+  >>> module_grokker.grok('numbers', numbers) 
+  Traceback (most recent call last):
+    ...
+  GrokError: <BrokenGrokker object at ...> returns None instead of 
+  True or False.
+
+Let's also try this with a GlobalGrokker::
+
+  >>> class MyGrokker(GlobalGrokker):
+  ...   def grok(self, name, module):
+  ...     return "Foo"
+  >>> module_grokker = ModuleGrokker()
+  >>> module_grokker.register(MyGrokker())
+  >>> module_grokker.grok('numbers', numbers)
+  Traceback (most recent call last):
+    ...
+  GrokError: <MyGrokker object at ...> returns 'Foo' instead of True or False.
+
+Meta Grokkers
+-------------
+
+Meta grokkers are grokkers that grok grokkers. This mechanism can be
+used to extend Martian. Let's register a ``ClassMetaGrokker`` that
+looks for subclasses of ``ClassGrokker``::
+
+  >>> from martian.core import MetaGrokker
+  >>> class ClassMetaGrokker(MetaGrokker):
+  ...   component_class = ClassGrokker
+  >>> multi_grokker = MultiGrokker()
+  >>> multi_grokker.register(ClassMetaGrokker(multi_grokker))
+
+``multi_grokker`` should now grok subclasses of ``ClassGrokker``, such
+as ``AnimalGrokker``::
+
+  >>> all_animals = {} # clean out animal registry
+  >>> multi_grokker.grok('AnimalGrokker', AnimalGrokker)
+  True
+
+Our multi_grokker should now also be able to grok animals::
+
+  >>> class Woodpecker(animal.Animal):
+  ...   pass
+  >>> multi_grokker.grok('Woodpecker', Woodpecker)
+  True
+
+A ``MetaMultiGrokker`` is a ``MultiGrokker`` that comes preconfigured with
+grokkers for ``ClassGrokker``, ``InstanceGrokker`` and ``GlobalGrokker``::
+
+  >>> from martian import MetaMultiGrokker
+  >>> multi_grokker = MetaMultiGrokker()
+
+It works for ``ClassGrokker``::
+  
+  >>> all_animals = {}
+  >>> multi_grokker.grok('AnimalGrokker', AnimalGrokker)
+  True
+  >>> multi_grokker.grok('Woodpecker', Woodpecker)
+  True
+  >>> all_animals
+  {'Woodpecker': <class 'Woodpecker'>}
+
+and for ``InstanceGrokker``::
+
+  >>> color.all_colors = {}
+  >>> multi_grokker.grok('ColorGrokker', ColorGrokker)
+  True
+  >>> multi_grokker.grok('color', Color(255, 0, 0))
+  True
+  >>> color.all_colors
+  {'color': <Color 255 0 0>}
+
+and for ``GlobalGrokker``::
+
+  >>> read_amount = {}
+  >>> multi_grokker.grok('AmountGrokker', AmountGrokker)
+  True
+  >>> grokker.grok('g', g)
+  True
+  >>> read_amount[None]
+  50
+
+We can clear the meta multi grokker::
+
+  >>> multi_grokker.clear()
+
+It won't grok particular classes or instances anymore::
+
+  >>> multi_grokker.grok('Woodpecker', Woodpecker)
+  False 
+  >>> multi_grokker.grok('color', Color(255, 0, 0))
+  False
+
+It can still grok grokkers::
+
+  >>> multi_grokker.grok('ColorGrokker', ColorGrokker)
+  True
+
+Executing meta grokkers only once
+---------------------------------
+
+In case of ``ClassGrokker`` and all other grokkers that are grokked
+by meta grokkers, we only want the grokking to occur once even if
+the same module (or package) is grokked twice::
+
+  >>> class TestOnce(object):
+  ...   pass
+  >>> executed = []
+  >>> class somemodule(FakeModule):
+  ...   class TestGrokker(ClassGrokker):
+  ...     component_class = TestOnce
+  ...     def grok(self, name, obj):
+  ...        executed.append(name)
+  ...        return True
+  >>> somemodule = fake_import(somemodule)
+  >>> module_grokker = ModuleGrokker(MetaMultiGrokker())
+
+Let's grok the module once::
+
+  >>> module_grokker.grok('somemodule', somemodule)
+  True
+
+Let's grok it twice::
+  
+  >>> module_grokker.grok('somemodule', somemodule)
+  True
+
+Even though we have grokked it twice, it is still only registered once. We
+can show this by actually having it grok a ``TestOnce`` subclass::
+
+  >>> class anothermodule(FakeModule):
+  ...   class TestSub(TestOnce):
+  ...      pass
+  >>> anothermodule = fake_import(anothermodule)
+  >>> module_grokker.grok('anothermodule', anothermodule)
+  True
+  >>> executed
+  ['TestSub']
+
+This also works for instance grokkers::
+
+  >>> class TestInstanceOnce(object):
+  ...   pass
+  >>> executed = []
+  >>> class somemodule(FakeModule):
+  ...   class TestGrokker(InstanceGrokker):
+  ...     component_class = TestInstanceOnce
+  ...     def grok(self, name, obj):
+  ...        executed.append(name)
+  ...        return True
+  >>> somemodule = fake_import(somemodule)
+  >>> module_grokker.clear()
+  >>> module_grokker.grok('somemodule', somemodule) # once
+  True
+  >>> module_grokker.grok('somemodule', somemodule) # twice
+  True
+  >>> class anothermodule(FakeModule):
+  ...   test = TestInstanceOnce()
+  >>> anothermodule = fake_import(anothermodule)
+  >>> module_grokker.grok('anothermodule', anothermodule)
+  True
+  >>> executed
+  ['test']
+
+It also works for global grokkers::
+
+  >>> executed = []
+  >>> class somemodule(FakeModule):
+  ...   class TestGrokker(GlobalGrokker):
+  ...     def grok(self, name, obj):
+  ...       executed.append(name)
+  ...       return True
+  >>> somemodule = fake_import(somemodule)
+  >>> module_grokker.clear()
+  >>> module_grokker.grok('somemodule', somemodule) # once
+  True
+  >>> module_grokker.grok('somemodule', somemodule) # twice
+  True
+
+The second grokking will already make ``somemodule`` grokked::
+
+  >>> executed
+  ['somemodule']
+
+Now let's grok another module::
+
+  >>> class anothermodule(FakeModule):
+  ...   pass
+  >>> anothermodule = fake_import(anothermodule)
+  >>> module_grokker.grok('anothermodule', anothermodule)
+  True
+  >>> executed
+  ['somemodule', 'anothermodule']
+
+Priority
+--------
+
+When grokking a module using a ``ModuleGrokker``, grokker execution
+can be determined by their priority. By default, grokkers have a
+priority of ``0``. Let's define two base classes, ``A`` and ``B``, 
+which can be grokked::
+
+  >>> class A(object):
+  ...   pass
+
+  >>> class B(object):
+  ...   pass
+
+Let's define a special kind of class grokker that records the order in
+which names get grokked::
+
+  >>> order = []
+  >>> class OrderGrokker(ClassGrokker):
+  ...   def grok(self, name, obj):
+  ...     order.append(name)
+  ...     return True
+
+Now we define two grokkers for subclasses of ``A`` and ``B``, where
+the ``BGrokker`` has a higher priority::
+
+  >>> class AGrokker(OrderGrokker):
+  ...   component_class = A
+  >>> class BGrokker(OrderGrokker):
+  ...   component_class = B
+  ...   priority = 10
+
+Let's register these grokkers::
+
+  >>> multi_grokker = MetaMultiGrokker()
+  >>> multi_grokker.grok('AGrokker', AGrokker)
+  True
+  >>> multi_grokker.grok('BGrokker', BGrokker)
+  True
+
+Let's create a module containing ``A`` and ``B`` subclasses::
+
+  >>> class mymodule(FakeModule):
+  ...   class ASub(A):
+  ...     pass
+  ...   class BSub(B):
+  ...     pass
+  >>> mymodule = fake_import(mymodule)
+
+We'll grok it::
+
+  >>> module_grokker = ModuleGrokker(multi_grokker)
+  >>> module_grokker.grok('mymodule', mymodule)
+  True
+
+Since the ``BGrokker`` has a higher priority, we expect the following
+order of grokking::
+
+  >>> order 
+  ['BSub', 'ASub']
+
+This also works for GlobalGrokkers. We will define a GlobalGrokker
+that has a higher priority than the default, but lower than B::
+
+  >>> class MyGlobalGrokker(GlobalGrokker):
+  ...   priority = 5
+  ...   def grok(self, name, obj):
+  ...     order.append(name)
+  ...     return True
+  >>> multi_grokker.grok('MyGlobalGrokker', MyGlobalGrokker)
+  True
+
+We will grok the module again::
+  
+  >>> order = []
+  >>> module_grokker.grok('mymodule', mymodule)
+  True
+
+This time, the global grokker should appear after 'BSub' but before 'ASub'::
+
+  >>> order
+  ['BSub', 'mymodule', 'ASub']
+
+


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/README.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,4 @@
+from core import ModuleGrokker, MultiGrokker, MetaMultiGrokker, grok_dotted_name,\
+     grok_package, grok_module
+from components import GlobalGrokker, ClassGrokker, InstanceGrokker
+from util import scan_for_classes


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/components.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/components.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/components.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,56 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+from zope.interface import implements
+
+from martian.interfaces import IGrokker, IComponentGrokker
+from martian import util
+
+NOT_DEFINED = object()
+
+class GrokkerBase(object):
+    implements(IGrokker)
+
+    priority = 0
+    
+    def grok(self, name, obj, **kw):
+        raise NotImplementedError
+
+    
+class GlobalGrokker(GrokkerBase):
+    """Grokker that groks once per module.
+    """
+
+    def grok(self, name, obj, **kw):
+        raise NotImplementedError
+    
+
+class ComponentGrokkerBase(GrokkerBase):
+    implements(IComponentGrokker)
+
+    component_class = NOT_DEFINED
+
+    def grok(self, name, obj, **kw):
+        raise NotImplementedError
+
+
+class ClassGrokker(ComponentGrokkerBase):
+    """Grokker that groks classes in a module.
+    """
+    pass
+
+class InstanceGrokker(ComponentGrokkerBase):
+    """Grokker that groks instances in a module.
+    """
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/components.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/core.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/core.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/core.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,222 @@
+import types, inspect
+
+from zope.interface import implements
+
+from martian.interfaces import IGrokker, IMultiGrokker
+from martian import util, scan
+from martian.components import (GrokkerBase, ClassGrokker, InstanceGrokker,
+                                GlobalGrokker)
+from martian.error import GrokError
+
+class MultiGrokkerBase(GrokkerBase):
+    implements(IMultiGrokker)
+
+    def register(self, grokker):
+        raise NotImplementedError
+    
+    def grok(self, name, obj, **kw):
+        grokked_status = False
+
+        for g, name, obj in self.grokkers(name, obj):
+            grokked = g.grok(name, obj, **kw)
+            if grokked not in (True, False):
+                raise GrokError(
+                    "%r returns %r instead of True or False." %
+                    (g, grokked), None)
+            if grokked:
+                grokked_status = True
+        
+        return grokked_status
+
+    def clear(self):
+        raise NotImplementedError
+    
+    def grokkers(self, name, obj):
+        raise NotImplementedError
+
+class ModuleGrokker(MultiGrokkerBase):
+  
+    def __init__(self, grokker=None, prepare=None, finalize=None):
+        if grokker is None:
+            grokker = MultiGrokker()
+        self._grokker = grokker
+        self.prepare = prepare
+        self.finalize = finalize
+        
+    def register(self, grokker):
+        self._grokker.register(grokker)
+
+    def clear(self):
+        self._grokker.clear()
+    
+    def grok(self, name, module, **kw):
+        grokked_status = False
+
+        # prepare module grok - this can also influence the kw dictionary
+        if self.prepare is not None:
+            self.prepare(name, module, kw)
+
+        # sort grokkers by priority
+        grokkers = sorted(self.grokkers(name, module),
+                          key=lambda (grokker, name, obj): grokker.priority,
+                          reverse=True)
+        
+        for g, name, obj in grokkers:
+            grokked = g.grok(name, obj, **kw)
+            if grokked not in (True, False):
+                raise GrokError(
+                    "%r returns %r instead of True or False." %
+                    (g, grokked), None)
+            if grokked:
+                grokked_status = True
+                
+        # finalize module grok
+        if self.finalize is not None:
+            self.finalize(name, module, kw)
+
+        return grokked_status
+
+    def grokkers(self, name, module):
+        grokker = self._grokker
+        # get any global grokkers
+        for t in grokker.grokkers(name, module):
+            yield t
+        
+        # try to grok everything in module
+        for name in dir(module):
+            if name.startswith('__grok_'):
+                continue
+            obj = getattr(module, name)
+            if not util.defined_locally(obj, module.__name__):
+                continue
+            if util.is_baseclass(name, obj):
+                continue
+            for t in grokker.grokkers(name, obj):
+                yield t
+
+class MultiInstanceOrClassGrokkerBase(MultiGrokkerBase):
+
+    def __init__(self):
+        self.clear()
+        
+    def register(self, grokker):
+        key = grokker.component_class
+        grokkers = self._grokkers.setdefault(key, [])
+        for g in grokkers:
+            if g.__class__ is grokker.__class__:
+                return
+        grokkers.append(grokker)
+
+    def clear(self):
+        self._grokkers = {}
+
+    def grokkers(self, name, obj):
+        used_grokkers = set()
+        for base in self.get_bases(obj):
+            grokkers = self._grokkers.get(base)
+            if grokkers is None:
+                continue
+            for grokker in grokkers:
+                if grokker not in used_grokkers:
+                    yield grokker, name, obj
+                    used_grokkers.add(grokker)
+
+class MultiInstanceGrokker(MultiInstanceOrClassGrokkerBase):
+    def get_bases(self, obj):
+        return inspect.getmro(obj.__class__)
+
+class MultiClassGrokker(MultiInstanceOrClassGrokkerBase):
+    def get_bases(self, obj):
+        if type(obj) is types.ModuleType:
+            return []
+        return inspect.getmro(obj)
+
+class MultiGlobalGrokker(MultiGrokkerBase):
+
+    def __init__(self):
+        self.clear()
+
+    def register(self, grokker):
+        for g in self._grokkers:
+            if grokker.__class__ is g.__class__:
+                return
+        self._grokkers.append(grokker)
+
+    def clear(self):
+        self._grokkers = []
+
+    def grokkers(self, name, module):
+        for grokker in self._grokkers:
+            yield grokker, name, module
+    
+class MultiGrokker(MultiGrokkerBase):
+    
+    def __init__(self):
+        self.clear()
+        
+    def register(self, grokker):
+        if isinstance(grokker, InstanceGrokker):
+            self._multi_instance_grokker.register(grokker)
+        elif isinstance(grokker, ClassGrokker):
+            self._multi_class_grokker.register(grokker)
+        elif isinstance(grokker, GlobalGrokker):
+            self._multi_global_grokker.register(grokker)
+        else:
+            assert 0, "Unknown type of grokker: %r" % grokker
+
+    def clear(self):
+        self._multi_instance_grokker = MultiInstanceGrokker()
+        self._multi_class_grokker = MultiClassGrokker()
+        self._multi_global_grokker = MultiGlobalGrokker()
+
+    def grokkers(self, name, obj):
+        obj_type = type(obj)
+        if obj_type in (type, types.ClassType):
+            return self._multi_class_grokker.grokkers(name, obj)
+        elif obj_type is types.ModuleType:
+            return self._multi_global_grokker.grokkers(name, obj)
+        else:
+            return self._multi_instance_grokker.grokkers(name, obj)
+        
+class MetaMultiGrokker(MultiGrokker):
+    """Multi grokker which comes pre-registered with meta-grokkers.
+    """
+    def clear(self):
+        super(MetaMultiGrokker, self).clear()
+        # bootstrap the meta-grokkers
+        self.register(ClassMetaGrokker(self))
+        self.register(InstanceMetaGrokker(self))
+        self.register(GlobalMetaGrokker(self))
+
+def grok_dotted_name(dotted_name, grokker, **kw):
+    module_info = scan.module_info_from_dotted_name(dotted_name)
+    grok_package(module_info, grokker, **kw)
+    
+def grok_package(module_info, grokker, **kw):
+    grok_module(module_info, grokker, **kw)
+    for sub_module_info in module_info.getSubModuleInfos():
+        grok_package(sub_module_info, grokker, **kw)
+
+def grok_module(module_info, grokker, **kw):
+    grokker.grok(module_info.dotted_name, module_info.getModule(), **kw)
+    
+# deep meta mode here - we define grokkers that can pick up the
+# three kinds of grokker: ClassGrokker, InstanceGrokker and ModuleGrokker
+class MetaGrokker(ClassGrokker):
+    def __init__(self, multi_grokker):
+        """multi_grokker - the grokker to register grokkers with.
+        """
+        self.multi_grokker = multi_grokker
+        
+    def grok(self, name, obj, **kw):
+        self.multi_grokker.register(obj())
+        return True
+    
+class ClassMetaGrokker(MetaGrokker):
+    component_class = ClassGrokker
+
+class InstanceMetaGrokker(MetaGrokker):
+    component_class = InstanceGrokker
+
+class GlobalMetaGrokker(MetaGrokker):
+    component_class = GlobalGrokker


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/core.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/directive.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/directive.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/directive.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,191 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Grok directives.
+"""
+
+import sys
+import inspect
+
+from zope import interface
+from zope.interface.interfaces import IInterface
+
+from martian import util
+from martian.error import GrokImportError
+
+class IDirectiveContext(interface.Interface):
+    description = interface.Attribute("The correct place in which the "
+                                      "directive can be used.")
+
+    def matches(frame):
+        """returns whether the given frame is the correct place in
+        which the directive can be used.
+        """
+
+class ClassDirectiveContext(object):
+    interface.implements(IDirectiveContext)
+    
+    description = "class"
+
+    def matches(self, frame):
+        return util.frame_is_class(frame)
+
+    
+class ModuleDirectiveContext(object):
+    interface.implements(IDirectiveContext)
+    
+    description = "module"
+
+    def matches(self, frame):
+        return util.frame_is_module(frame)
+    
+
+class ClassOrModuleDirectiveContext(object):
+    interface.implements(IDirectiveContext)
+    
+    description = "class or module"
+
+    def matches(self, frame):
+        return util.frame_is_module(frame) or util.frame_is_class(frame)
+
+
+class Directive(object):
+    """
+    Directive sets a value into the context's locals as __<name>__
+    ('.' in the name are replaced with '_').
+    """
+
+    def __init__(self, name, directive_context):
+        self.name = name
+        self.local_name = '__%s__' % name.replace('.', '_')
+        self.directive_context = directive_context
+
+    def __call__(self, *args, **kw):
+        self.check_argument_signature(*args, **kw)
+        self.check_arguments(*args, **kw)
+
+        frame = sys._getframe(1)
+        self.check_directive_context(frame)
+
+        value = self.value_factory(*args, **kw)
+        return self.store(frame, value)
+
+    def check_arguments(self, *args, **kw):
+        raise NotImplementedError
+
+    # to get a correct error message, we construct a function that has
+    # the same signature as check_arguments(), but without "self".
+    def check_argument_signature(self, *arguments, **kw):
+        args, varargs, varkw, defaults = inspect.getargspec(
+            self.check_arguments)
+        argspec = inspect.formatargspec(args[1:], varargs, varkw, defaults)
+        exec("def signature_checker" + argspec + ": pass")
+        try:
+            signature_checker(*arguments, **kw)
+        except TypeError, e:
+            message = e.args[0]
+            message = message.replace("signature_checker()", self.name)
+            raise TypeError(message)
+
+    def check_directive_context(self, frame):
+        if not self.directive_context.matches(frame):
+            raise GrokImportError("%s can only be used on %s level."
+                                  % (self.name,
+                                     self.directive_context.description))
+
+    def value_factory(self, *args, **kw):
+        raise NotImplementedError
+
+    def store(self, frame, value):
+        raise NotImplementedError
+
+
+class OnceDirective(Directive):
+    def store(self, frame, value):
+        if self.local_name in frame.f_locals:
+            raise GrokImportError("%s can only be called once per %s."
+                                  % (self.name,
+                                     self.directive_context.description))
+        frame.f_locals[self.local_name] = value
+
+
+class MarkerDirective(OnceDirective):
+    """A directive without argument that places a marker.
+    """
+    def value_factory(self):
+        return True
+
+    def check_arguments(self):
+        pass
+
+class MultipleTimesDirective(Directive):
+    def store(self, frame, value):
+        values = frame.f_locals.get(self.local_name, [])
+        values.append(value)
+        frame.f_locals[self.local_name] = values
+
+
+class SingleValue(object):
+
+    # Even though the value_factory is called with (*args, **kw),
+    # we're safe since check_arguments would have bailed out with a
+    # TypeError if the number arguments we were called with was not
+    # what we expect here.
+    def value_factory(self, value):
+        return value
+
+
+class BaseTextDirective(object):
+    """
+    Base directive that only accepts unicode/ASCII values.
+    """
+
+    def check_arguments(self, value):
+        if util.not_unicode_or_ascii(value):
+            raise GrokImportError("You can only pass unicode or ASCII to "
+                                  "%s." % self.name)
+
+
+class SingleTextDirective(BaseTextDirective, SingleValue, OnceDirective):
+    """
+    Directive that accepts a single unicode/ASCII value, only once.
+    """
+
+
+class MultipleTextDirective(BaseTextDirective, SingleValue,
+                            MultipleTimesDirective):
+    """
+    Directive that accepts a single unicode/ASCII value, multiple times.
+    """
+
+
+class InterfaceOrClassDirective(SingleValue, OnceDirective):
+    """
+    Directive that only accepts classes or interface values.
+    """
+
+    def check_arguments(self, value):
+        if not (IInterface.providedBy(value) or util.isclass(value)):
+            raise GrokImportError("You can only pass classes or interfaces to "
+                                  "%s." % self.name)
+
+
+class InterfaceDirective(SingleValue, OnceDirective):
+    """
+    Directive that only accepts interface values.
+    """
+
+    def check_arguments(self, value):
+        if not (IInterface.providedBy(value)):
+            raise GrokImportError("You can only pass interfaces to "
+                                  "%s." % self.name)


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/directive.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/directive.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/directive.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/directive.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,200 @@
+Directives
+==========
+
+A martian directive is a special function call that causes information
+to be set on module or class level. This information is set as a
+Python module is imported, so should do the minimum amount of work (as
+import side-effects are bad). The idea is that this information can
+then be picked up by a martian-based framework during grok time.
+
+Martian has an infrastructure to make it easy to define new
+directives.
+
+Directive contexts
+------------------
+
+If a directive is given ``ModuleDirectiveContext`` it can only work in
+real modules::
+
+  >>> from martian.directive import SingleTextDirective, ModuleDirectiveContext
+  >>> foo = SingleTextDirective('grok.foo', ModuleDirectiveContext())
+
+We cannot show a working example of the ``foo`` directive in this
+doctest as it is not a real module. It would look like this::
+  
+   foo('hello world')
+
+We have placed this code in a real module and will import it::
+
+  >>> from martian.tests.directive import modulecontext
+
+We expect modulecontext to contain a special attribute ``__grok_foo__``
+with the string ``'hello world'``::
+
+  >>> modulecontext.__grok_foo__
+  'hello world'
+
+This directive cannot be used in a class as it's not allowed by its context::
+ 
+  >>> class Test(object):
+  ...   foo('hello world')
+  Traceback (most recent call last):
+   ...
+  GrokImportError: grok.foo can only be used on module level.
+
+Now let's define a directive that can only work in classes::
+
+  >>> from martian.directive import ClassDirectiveContext
+  >>> bar = SingleTextDirective('grok.bar', ClassDirectiveContext())
+
+It won't work in a module::
+
+  >>> from martian.tests.directive import classcontextbroken
+  Traceback (most recent call last):
+    ...
+  GrokImportError: grok.bar can only be used on class level.
+
+It will work in a class context::
+
+  >>> class Test(object):
+  ...   bar('hello world')
+  >>> Test.__grok_bar__
+  'hello world'
+
+Now let's define a directive that can be used both on module-level as
+well as on class-level::
+
+  >>> from martian.directive import ClassOrModuleDirectiveContext
+  >>> qux = SingleTextDirective('grok.qux', ClassOrModuleDirectiveContext())
+
+It can be used in a class::
+
+  >>> class Test(object):
+  ...   qux('hello world')
+  >>> Test.__grok_qux__
+  'hello world'
+
+It can also be used in a module::
+
+  >>> from martian.tests.directive import classormodulecontext
+  >>> classormodulecontext.__grok_qux__
+  'hello world'
+
+Calling a directive once or multiple times
+------------------------------------------
+
+Directives can either be called once in a particular context, or
+multiple times. Let's define a type of directive that can only be
+called once::
+  
+  >>> from martian.directive import OnceDirective, SingleValue, BaseTextDirective
+  >>> class MyDirective(BaseTextDirective, SingleValue, OnceDirective):
+  ...   pass
+  >>> hoi = MyDirective('hoi', ClassDirectiveContext())
+
+When we try to use it twice, we get an error::
+
+  >>> class Test(object):
+  ...   hoi('once')
+  ...   hoi('twice')
+  Traceback (most recent call last):
+    ...
+  GrokImportError: hoi can only be called once per class.
+
+This also works for module-level directives::
+
+  >>> from martian.tests.directive import onlyoncemodulecontext
+  Traceback (most recent call last):
+    ...
+  GrokImportError: hoi can only be called once per module.
+
+Now let's define a directive that can be called multiple times::
+
+  >>> from martian.directive import MultipleTimesDirective
+  >>> class MyDirective(BaseTextDirective, SingleValue, MultipleTimesDirective):
+  ...   pass
+  >>> dag = MyDirective('dag', ClassDirectiveContext())
+
+It will allow you to use it multiple times::
+ 
+  >>> class Test(object):
+  ...   dag('once')
+  ...   dag('twice')
+
+The underlying annotation will have stored the multiple values::
+
+  >>> Test.__dag__
+  ['once', 'twice']
+
+Directive values
+----------------
+
+A ``BaseTextDirective`` directive accepts unicode or plain ascii values::
+
+ >>> class Test(object):
+ ...   hoi('hello')
+ >>> class Test(object):
+ ...   hoi(u'è')
+
+It won't accept values in another encoding::
+
+ >>> class Test(object):
+ ...   hoi(u'è'.encode('latin-1'))
+ Traceback (most recent call last):
+   ...
+ GrokImportError: You can only pass unicode or ASCII to hoi.
+ >>> class Test(object):
+ ...   hoi(u'è'.encode('UTF-8'))
+ Traceback (most recent call last):
+   ...
+ GrokImportError: You can only pass unicode or ASCII to hoi.
+
+A ``InterfaceOrClassDirective`` only accepts class or interface objects::
+
+  >>> from martian.directive import InterfaceOrClassDirective
+  >>> class MyDirective(InterfaceOrClassDirective, SingleValue, OnceDirective):
+  ...   pass
+  >>> hello = MyDirective('hello', ClassDirectiveContext())
+  >>> class SomeClass(object):
+  ...    pass
+  >>> class Test(object):
+  ...   hello(SomeClass)
+  >>> class SomeOldStyleClass:
+  ...   pass
+  >>> class Test(object):
+  ...   hello(SomeOldStyleClass)
+  >>> from zope.interface import Interface
+  >>> class ISomeInterface(Interface):
+  ...   pass
+  >>> class Test(object):
+  ...   hello(ISomeInterface)
+
+But not anything else::
+  
+  >>> class Test(object):
+  ...   hello(None)
+  Traceback (most recent call last):
+   ...
+  GrokImportError: You can only pass classes or interfaces to hello.
+  >>> class Test(object):
+  ...   hello('foo')
+  Traceback (most recent call last):
+   ...
+  GrokImportError: You can only pass classes or interfaces to hello.
+
+An ``InterfaceDirective`` accepts only interfaces::
+
+  >>> from martian.directive import InterfaceDirective
+  >>> class MyDirective(InterfaceDirective, SingleValue, OnceDirective):
+  ...   pass
+  >>> hello2 = MyDirective('hello2', ClassDirectiveContext())
+  >>> class Test(object):
+  ...   hello2(ISomeInterface)
+
+But not classes::
+
+  >>> class Test(object):
+  ...   hello2(SomeClass)
+  Traceback (most recent call last):
+    ...
+  GrokImportError: You can only pass interfaces to hello2.


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/directive.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/error.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/error.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/error.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,21 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+class GrokError(Exception):
+    def __init__(self, message, component):
+        Exception.__init__(self, message)
+        self.component = component
+
+class GrokImportError(ImportError):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/error.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/interfaces.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/interfaces.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/interfaces.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,104 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+from zope.interface import Interface, Attribute
+
+class IGrokker(Interface):
+    priority = Attribute('Priority during module grokking.')
+
+    def grok(name, obj, **kw):
+        """Grok obj.
+
+        name - name of object (in module)
+        obj - object to grok
+        **kw - optional parameters passed along the grokking process.
+
+        May do extra filtering based on name or obj.
+
+        Returns True if grok is attempted, False if object is filtered
+        out by this grokker.
+        """
+    
+class IComponentGrokker(IGrokker):
+    """A grokker that groks components in a module.
+
+    Components may be instances or classes indicated by component_class.
+    """
+    component_class = Attribute('Class of the component to match')
+    
+class IMultiGrokker(IComponentGrokker):
+    """A grokker that is composed out of multiple grokkers.
+    """
+    def register(grokker):
+        """Register a grokker.
+        """
+
+    def clear():
+        """Clear all grokkers and go back to initial state.
+        """
+
+    def grokkers(name, obj):
+        """Iterable of all grokkers that apply to obj.
+        """
+
+class IModuleInfo(Interface):
+    def getModule():
+        """Get the module object this module info is representing.
+
+        In case of packages, gives back the module object for the package's
+        __init__.py
+        """
+
+    def isPackage():
+        """Returns True if this module is a package.
+        """
+
+    def getSubModuleInfos():
+        """Get module infos for any sub modules.
+
+        In a module, this will always return an empty list.
+        """
+
+    def getSubModuleInfo(name):
+        """Get sub module info for <name>.
+
+        In a package, give module info for sub-module.
+        Returns None if no such sub module is found. In a module,
+        always returns None.
+        """
+
+    def getResourcePath(name):
+        """Get the absolute path of a resource directory.
+
+        The resource directory will be 'relative' to this package or
+        module.
+
+        Case one: get the resource directory with name <name> from the same
+        directory as this module
+
+        Case two: get the resource directory with name <name> from the children
+        of this package
+        """
+
+    def getAnnotation(key, default):
+        """Given a key, get annotation object from module.
+
+        The annotation key is a dotted name. All dots are replaced
+        with underscores and the result is pre and post-fixed by
+        double underscore. For instance 'grok.name' will be translated
+        to '__grok_name__'.
+        
+        Uses default if no such annotation found.
+        """
+


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/scan.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/scan.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/scan.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,153 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Scanning packages and modules
+"""
+
+import os
+
+from zope.interface import implements
+
+from martian.interfaces import IModuleInfo
+
+def is_package(path):
+    if not os.path.isdir(path):
+        return False
+    init_py = os.path.join(path, '__init__.py')
+    init_pyc = init_py + 'c'
+    # Check whether either __init__.py or __init__.pyc exist
+    return os.path.isfile(init_py) or os.path.isfile(init_pyc)
+
+
+class ModuleInfo(object):
+    implements(IModuleInfo)
+    
+    def __init__(self, path, dotted_name):
+        # Normalize .pyc files to .py
+        if path.endswith('c'):
+            path = path[:-1]
+        self.path = path
+        self.dotted_name = dotted_name
+
+        name_parts = dotted_name.split('.')
+        self.name = name_parts[-1]
+        if self.isPackage():
+            self.package_dotted_name = dotted_name
+        else:
+            self.package_dotted_name = '.'.join(name_parts[:-1])
+
+        self._module = None
+
+    def getResourcePath(self, name):
+        """Get the absolute path of a resource directory 'relative' to this
+        package or module.
+
+        Case one: get the resource directory with name <name> from the same
+        directory as this module
+
+        Case two: get the resource directory with name <name> from the children
+        of this package
+        """
+        return os.path.join(os.path.dirname(self.path), name)
+
+    def getSubModuleInfos(self):
+        if not self.isPackage():
+            return []
+        directory = os.path.dirname(self.path)
+        module_infos = []
+        seen = []
+        for entry in sorted(os.listdir(directory)):
+            entry_path = os.path.join(directory, entry)
+            name, ext = os.path.splitext(entry)
+            dotted_name = self.dotted_name + '.' + name
+
+            # Case one: modules
+            if (os.path.isfile(entry_path) and ext in ['.py', '.pyc']):
+                if name == '__init__':
+                    continue
+                # Avoid duplicates when both .py and .pyc exist
+                if name in seen:
+                    continue
+                seen.append(name)
+                module_infos.append(ModuleInfo(entry_path, dotted_name))
+            # Case two: packages
+            elif is_package(entry_path):
+                # We can blindly use __init__.py even if only
+                # __init__.pyc exists because we never actually use
+                # that filename.
+                module_infos.append(ModuleInfo(
+                    os.path.join(entry_path, '__init__.py'), dotted_name))
+        return module_infos
+
+    def getSubModuleInfo(self, name):
+        path = os.path.join(os.path.dirname(self.path), name)
+        if is_package(path):
+            return ModuleInfo(os.path.join(path, '__init__.py'),
+                              '%s.%s' % (self.package_dotted_name, name))
+        elif os.path.isfile(path + '.py') or os.path.isfile(path + '.pyc'):
+                return ModuleInfo(path + '.py',
+                                  '%s.%s' % (self.package_dotted_name, name))
+        else:
+            return None
+        
+
+    def getAnnotation(self, key, default):
+        key = key.replace('.', '_')
+        key = '__%s__' % key
+        module = self.getModule()
+        return getattr(module, key, default)
+
+    def getModule(self):
+        if self._module is None:
+            self._module = resolve(self.dotted_name)
+        return self._module
+
+    def isPackage(self):
+        return self.path.endswith('__init__.py')
+
+    def __repr__(self):
+        return "<ModuleInfo object for '%s'>" % self.dotted_name
+
+
+def module_info_from_dotted_name(dotted_name):
+    module = resolve(dotted_name)
+    return ModuleInfo(module.__file__, dotted_name)
+
+def module_info_from_module(module):
+    return ModuleInfo(module.__file__, module.__name__)
+
+
+# taken from zope.dottedname.resolve
+def resolve(name, module=None):
+    name = name.split('.')
+    if not name[0]:
+        if module is None:
+            raise ValueError("relative name without base module")
+        module = module.split('.')
+        name.pop(0)
+        while not name[0]:
+            module.pop()
+            name.pop(0)
+        name = module + name
+
+    used = name.pop(0)
+    found = __import__(used)
+    for n in name:
+        used += '.' + n
+        try:
+            found = getattr(found, n)
+        except AttributeError:
+            __import__(used)
+            found = getattr(found, n)
+
+    return found


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/scan.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/scan.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/scan.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/scan.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,164 @@
+Scanning modules
+================
+
+Martian can grok modules or packages. In order to grok packages, it
+needs to scan all modules in it. The martian.scan package provides an
+abstraction over packages and modules that helps with the scanning
+process.
+
+  >>> from martian.scan import module_info_from_dotted_name
+  
+We have provided a special test fixture package called stoneage that we are
+going to scan, in ``martian.tests.stoneage``.
+
+Modules
+-------
+
+The scanning module defines a class ``ModuleInfo`` that provides
+information about a module or a package. Let's take a look at the
+``cave`` module in the stone-age package::
+
+  >>> module_info = module_info_from_dotted_name('martian.tests.stoneage.cave')
+  
+We get a ``ModuleInfo`` object representing the ``cave module::
+
+  >>> module_info
+  <ModuleInfo object for 'martian.tests.stoneage.cave'>
+  
+``cave`` is a module, not a package.
+
+  >>> module_info.isPackage()
+  False
+
+We can retrieve the name of the module::
+
+  >>> module_info.name
+  'cave'
+
+We can also retrieve the dotted name of the module::
+
+  >>> module_info.dotted_name
+  'martian.tests.stoneage.cave'
+
+And the dotted name of the package the module is in::
+
+  >>> module_info.package_dotted_name
+  'martian.tests.stoneage'
+
+It is possible to get the actual module object that the ModuleInfo
+object stands for, in this case the package's ``cave.py``::
+
+  >>> module = module_info.getModule()
+  >>> module
+  <module 'martian.tests.stoneage.cave' from '...cave.py...'>
+
+We can store a module-level annotation in the module::
+
+  >>> module.__grok_foobar__ = 'GROK LOVE FOO'
+
+The ModuleInfo object allows us to retrieve the annotation again::
+
+  >>> module_info.getAnnotation('grok.foobar', None)
+  'GROK LOVE FOO'
+
+If a requested annotation does not exist, we get the default value::
+
+  >>> module_info.getAnnotation('grok.barfoo', 42)
+  42
+
+A module has no sub-modules in it (only packages have this)::
+
+  >>> module_info.getSubModuleInfos()
+  []
+
+Trying to retrieve any sub modules will give back None::
+
+  >>> print module_info.getSubModuleInfo('doesnotexist')
+  None
+
+Packages
+--------
+
+Now let's scan a package::
+
+  >>> module_info = module_info_from_dotted_name('martian.tests.stoneage')
+
+We will get a ModuleInfo instance representing the ``stoneage`` package::
+
+  >>> module_info
+  <ModuleInfo object for 'martian.tests.stoneage'>
+
+The object knows it is a package::
+
+  >>> module_info.isPackage()
+  True
+
+Like with the module, we can get the package's name::
+
+  >>> module_info.name
+  'stoneage'
+
+We can also get the package's dotted name back from it::
+
+  >>> module_info.dotted_name
+  'martian.tests.stoneage'
+
+It is also possible to get the dotted name of the nearest package the
+package resides in. This will always be itself::
+
+  >>> module_info.package_dotted_name
+  'martian.tests.stoneage'
+
+Now let's go into the package and a few sub modules that are in it::
+
+  >>> module_info.getSubModuleInfo('cave')
+  <ModuleInfo object for 'martian.tests.stoneage.cave'>
+
+  >>> module_info.getSubModuleInfo('hunt')
+  <ModuleInfo object for 'martian.tests.stoneage.hunt'>
+
+Trying to retrieve non-existing sub modules gives back None::
+
+  >>> print module_info.getSubModuleInfo('doesnotexist')
+  None
+
+It is possible to get the actual module object that the ModuleInfo
+object stands for, in this case the package's ``__init__.py``::
+
+  >>> module = module_info.getModule()
+  >>> module
+  <module 'martian.tests.stoneage' from '...__init__.py...'>
+
+A package has sub modules::
+
+  >>> sub_modules = module_info.getSubModuleInfos()
+  >>> sub_modules
+  [<ModuleInfo object for 'martian.tests.stoneage.cave'>,
+   <ModuleInfo object for 'martian.tests.stoneage.hunt'>,
+   <ModuleInfo object for 'martian.tests.stoneage.painting'>]
+
+Resource paths
+--------------
+
+Resources can be stored in a directory alongside a module (in their
+containing package).  We can get the path to such a resource directory
+using the ``getResourcePath`` method.
+
+For packages, a resource path will be a child of the package directory:
+
+  >>> import os.path
+  >>> expected_resource_path = os.path.join(os.path.dirname(
+  ...     module.__file__), 'stoneage-templates')
+  >>> resource_path = module_info.getResourcePath('stoneage-templates')
+  >>> resource_path == expected_resource_path
+  True
+
+For modules, a resource path will be a sibling of the module's file:
+
+  >>> cave_module_info = module_info_from_dotted_name(
+  ...    'martian.tests.stoneage.cave')
+  >>> expected_resource_path = os.path.join(os.path.dirname(
+  ...     cave_module_info.getModule().__file__), 'cave-templates')
+  >>> resource_path = cave_module_info.getResourcePath('cave-templates')
+  >>> resource_path == expected_resource_path
+  True


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/scan.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/classcontextbroken.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/classcontextbroken.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/classcontextbroken.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+from martian.directive import SingleTextDirective, ClassDirectiveContext
+
+bar = SingleTextDirective('grok.bar', ClassDirectiveContext())
+
+bar('hello world') # this won't work as not class context


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/classcontextbroken.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/classormodulecontext.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/classormodulecontext.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/classormodulecontext.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+from martian.directive import SingleTextDirective, ClassOrModuleDirectiveContext
+
+qux = SingleTextDirective('grok.qux', ClassOrModuleDirectiveContext())
+
+qux('hello world')


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/classormodulecontext.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/modulecontext.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/modulecontext.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/modulecontext.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+from martian.directive import SingleTextDirective, ModuleDirectiveContext
+
+foo = SingleTextDirective('grok.foo', ModuleDirectiveContext())
+
+foo('hello world')


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/modulecontext.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/onlyoncemodulecontext.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/onlyoncemodulecontext.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/onlyoncemodulecontext.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,10 @@
+from martian.directive import OnceDirective, SingleValue, BaseTextDirective
+from martian.directive import ModuleDirectiveContext
+
+class MyDirective(BaseTextDirective, SingleValue, OnceDirective):
+    pass
+
+hoi = MyDirective('hoi', ModuleDirectiveContext())
+
+hoi('once')
+hoi('twice')


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/directive/onlyoncemodulecontext.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+# this package is a test fixture for the scan tests.
+
+


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/cave.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/cave.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/cave.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+
+class Cave(object):
+    pass
+
+class Index(object):
+    pass
+
+index = Index()


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/cave.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/mammoth.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/mammoth.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/mammoth.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,6 @@
+
+class Mammoth(object):
+    pass
+
+class Index(object):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/mammoth.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/mammoth_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/mammoth_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/hunt/mammoth_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<h1>ME GROK HUNT MAMMOTH!</h1>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/notpackage/dummy.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/notpackage/dummy.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/notpackage/dummy.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# foo


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/notpackage/dummy.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/painting/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/painting/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/painting/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/stoneage/painting/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/test_all.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/test_all.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/test_all.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,72 @@
+import unittest
+from zope.testing import doctest
+import new, types
+
+class FakeModule(object):
+    pass
+
+def class_annotation_nobase(obj, name, default):
+    """This will only look in the given class obj for the annotation.
+
+    It will not look in the inheritance chain.
+    """
+    return obj.__dict__.get('__%s__' % name.replace('.', '_'), default)
+
+def fake_import(fake_module):
+    module = new.module(fake_module.__name__)
+    glob = {}
+    for name in dir(fake_module):
+        if name.startswith('__'):
+            continue
+        obj = getattr(fake_module, name)
+        glob[name] = obj
+        try:
+            obj = obj.im_func
+        except AttributeError:
+            pass
+        __module__ = None
+        try:
+            __module__ == obj.__dict__.get('__module__')
+        except AttributeError:
+            try:
+                __module__ = obj.__module__
+            except AttributeError:
+                pass
+        if __module__ is None or __module__ == '__builtin__':
+            try:
+                obj.__module__ = module.__name__
+            except AttributeError:
+                pass
+        setattr(module, name, obj)
+
+    # provide correct globals for functions
+    for name in dir(module):
+        if name.startswith('__'):
+            continue
+        obj = getattr(module, name)
+        try:
+            code = obj.func_code
+            new_func = new.function(code, glob, name)
+            new_func.__module__ = module.__name__
+            setattr(module, name, new_func)
+            glob[name] = new_func
+        except AttributeError:
+            pass
+    return module
+
+optionflags = doctest.NORMALIZE_WHITESPACE + doctest.ELLIPSIS
+
+globs = dict(FakeModule=FakeModule, fake_import=fake_import)
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTests([
+        doctest.DocFileSuite('../README.txt',
+                             globs=globs,
+                             optionflags=optionflags),
+        doctest.DocFileSuite('../scan.txt',
+                             optionflags=optionflags),
+        doctest.DocFileSuite('../directive.txt',
+                             optionflags=optionflags),
+        ])
+    return suite


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/test_all.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,2 @@
+# 
+


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/alpha/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/alpha/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/alpha/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,4 @@
+from martian.tests.testpackage import animal
+
+class Python(animal.Animal):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/alpha/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/animal.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/animal.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/animal.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,2 @@
+class Animal(object):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/animal.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/beta/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/beta/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/beta/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/beta/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/beta/three.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/beta/three.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/beta/three.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+from martian.tests.testpackage import animal
+
+class Lizard(animal.Animal):
+    pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/beta/three.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/one.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/one.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/one.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,10 @@
+import animal
+
+class Whale(animal.Animal):
+    pass
+
+class Dragon(animal.Animal):
+    pass
+
+class SpermWhale(Whale):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/one.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/two.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/two.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/two.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,4 @@
+import animal
+
+class Bear(animal.Animal):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/tests/testpackage/two.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/martian/src/martian/util.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/martian/src/martian/util.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/martian/src/martian/util.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,163 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Martian utility functions.
+"""
+
+import re
+import types
+import sys
+import inspect
+
+from zope import interface
+
+from martian.error import GrokError, GrokImportError
+
+def not_unicode_or_ascii(value):
+    if isinstance(value, unicode):
+        return False
+    if not isinstance(value, str):
+        return True
+    return is_not_ascii(value)
+
+is_not_ascii = re.compile(eval(r'u"[\u0080-\uffff]"')).search
+
+def isclass(obj):
+    """We cannot use ``inspect.isclass`` because it will return True
+    for interfaces"""
+    return isinstance(obj, (types.ClassType, type))
+
+
+def check_subclass(obj, class_):
+    if not isclass(obj):
+        return False
+    return issubclass(obj, class_)
+
+
+def caller_module():
+    return sys._getframe(2).f_globals['__name__']
+
+def is_baseclass(name, component):
+    return (type(component) is type and
+            (name.endswith('Base') or
+             class_annotation_nobase(component, 'grok.baseclass', False)))
+
+def class_annotation(obj, name, default):
+    return getattr(obj, '__%s__' % name.replace('.', '_'), default)
+
+def class_annotation_nobase(obj, name, default):
+    """This will only look in the given class obj for the annotation.
+
+    It will not look in the inheritance chain.
+    """
+    return obj.__dict__.get('__%s__' % name.replace('.', '_'), default)
+    
+def class_annotation_list(obj, name, default):
+    """This will process annotations that are lists correctly in the face of
+    inheritance.
+    """
+    if class_annotation(obj, name, default) is default:
+        return default
+
+    result = []
+    for base in reversed(obj.mro()):
+        list = class_annotation(base, name, [])
+        if list not in result:
+            result.append(list)
+
+    result_flattened = []
+    for entry in result:
+        result_flattened.extend(entry)
+    return result_flattened
+
+def defined_locally(obj, dotted_name):
+    obj_module = getattr(obj, '__grok_module__', None)
+    if obj_module is None:
+        obj_module = getattr(obj, '__module__', None)
+    return obj_module == dotted_name
+
+
+AMBIGUOUS_CONTEXT = object()
+def check_context(component, context):
+    if context is None:
+        raise GrokError("No module-level context for %r, please use "
+                        "grok.context." % component, component)
+    elif context is AMBIGUOUS_CONTEXT:
+        raise GrokError("Multiple possible contexts for %r, please use "
+                        "grok.context." % component, component)
+
+
+def check_implements_one(class_):
+    check_implements_one_from_list(list(interface.implementedBy(class_)),
+                                   class_)
+
+def check_implements_one_from_list(list, class_):
+    if len(list) < 1:
+        raise GrokError("%r must implement at least one interface "
+                        "(use grok.implements to specify)."
+                        % class_, class_)
+    elif len(list) > 1:
+        raise GrokError("%r is implementing more than one interface "
+                        "(use grok.provides to specify which one to use)."
+                        % class_, class_)
+
+
+def scan_for_classes(module, classes):
+    """Given a module, scan for classes.
+    """
+    result = []
+    for name in dir(module):
+        if name.startswith('__grok_'):
+            continue
+        obj = getattr(module, name)
+        if not defined_locally(obj, module.__name__):
+            continue
+        for class_ in classes:
+            if check_subclass(obj, class_):
+                result.append(obj)
+    return result
+
+def determine_module_context(module_info, models):
+    if len(models) == 0:
+        context = None
+    elif len(models) == 1:
+        context = models[0]
+    else:
+        context = AMBIGUOUS_CONTEXT
+
+    module_context = module_info.getAnnotation('grok.context', None)
+    if module_context:
+        context = module_context
+
+    return context
+
+
+def determine_class_context(class_, module_context):
+    context = class_annotation(class_, 'grok.context', module_context)
+    check_context(class_, context)
+    return context
+
+
+def methods_from_class(class_):
+    # XXX Problem with zope.interface here that makes us special-case
+    # __provides__.
+    candidates = [getattr(class_, name) for name in dir(class_)
+                  if name != '__provides__' ]
+    methods = [c for c in candidates if inspect.ismethod(c)]
+    return methods
+
+def frame_is_module(frame):
+    return frame.f_locals is frame.f_globals
+
+def frame_is_class(frame):
+    return '__module__' in frame.f_locals    


Property changes on: grok/branches/darrylcousins-martian-layers/martian/src/martian/util.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/setup.cfg
===================================================================
--- grok/branches/darrylcousins-martian-layers/setup.cfg	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/setup.cfg	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+[egg_info]
+tag_build = dev
+tag_svn_revision = true

Added: grok/branches/darrylcousins-martian-layers/setup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/setup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/setup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,67 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Setup
+
+$Id$
+"""
+import os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+setup(
+    name='grok',
+    version='0.9',
+    author='Grok Team',
+    author_email='grok-dev at zope.org',
+    url='https://launchpad.net/grok',
+    download_url='svn://svn.zope.org/repos/main/grok/trunk#egg=grok-dev',
+    description='Grok: Now even cavemen can use Zope 3!',
+    long_description=open('README.txt').read(),
+    license='ZPL',
+    packages = find_packages('src'),
+    include_package_data = True,
+    package_dir = {'':'src'},
+    dependency_links = ['http://download.zope.org/distribution'],
+    zip_safe = False,
+      install_requires=['setuptools',
+                        'zope.annotation',
+                        'zope.copypastemove',
+                        'zope.contentprovider',
+                        'zope.event',
+                        'zope.formlib',
+                        'zope.i18n',
+                        'zope.publisher',
+                        'zope.security',
+                        'zope.size',
+                        'zope.traversing',
+                        'zope.testbrowser',
+                        'zope.viewlet',
+                        'zope.app.securitypolicy',
+                        'zope.app.authentication',
+                        'zope.app.catalog',
+                        'zope.app.intid',
+                        'zope.app.keyreference',
+                        'zope.app.twisted',
+                        'zope.app.session',
+                        'zope.app.zcmlfiles',
+                        'zope.app.file',
+                        'simplejson',
+                        # -*- Extra requirements: -*-
+                        ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+    )


Property changes on: grok/branches/darrylcousins-martian-layers/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/setup.py.1
===================================================================
--- grok/branches/darrylcousins-martian-layers/setup.py.1	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/setup.py.1	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,84 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Setup
+
+$Id: setup.py 77034 2007-06-25 12:57:23Z srichter $
+"""
+import os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+setup(
+    name='grok',
+    version='0.9',
+    author='Grok Team',
+    author_email='grok-dev at zope.org',
+    url='https://launchpad.net/grok',
+    download_url='svn://svn.zope.org/repos/main/grok/trunk#egg=grok-dev',
+    description='Grok: Now even cavemen can use Zope 3!',
+    long_description=open('README.txt').read(),
+    license='ZPL',
+    packages = find_packages('src'),
+    include_package_data = True,
+    package_dir = {'':'src'},
+    install_requires = [
+        'setuptools',
+        'z3c.csvvocabulary',
+        'z3c.form',
+        'z3c.formui',
+        'z3c.layer',
+        'z3c.pagelet',
+        'z3c.template',
+        'z3c.viewlet',
+        'z3c.zrtresource',
+        'zc.resourcelibrary',
+        'zc.table',
+        'zope.annotation',
+        'zope.app.container',
+        'zope.app.catalog',
+        'zope.app.intid',
+        'zope.app.pagetemplate',
+        'zope.app.rotterdam',
+        'zope.app.session',
+        'zope.app.appsetup',
+        'zope.app.authentication',
+        'zope.app.component',
+        'zope.app.container',
+        'zope.app.error',
+        'zope.app.form',
+        'zope.app.publisher',
+        'zope.app.publication',
+        'zope.app.security',
+        'zope.app.securitypolicy',
+        'zope.app.twisted',
+        'zope.app.wsgi',
+        'zope.app.zcmlfiles',
+        'zope.contentprovider',
+        'zope.component',
+        'zope.interface',
+        'zope.location',
+        'zope.pagetemplate',
+        'zope.publisher',
+        'zope.rdb',
+        'zope.schema',
+        'zope.testbrowser',
+        'zope.traversing',
+        'zope.viewlet',
+        'simplejson',
+        ],
+    dependency_links = ['http://download.zope.org/distribution'],
+    zip_safe = False,
+    )

Added: grok/branches/darrylcousins-martian-layers/setup.py.orig
===================================================================
--- grok/branches/darrylcousins-martian-layers/setup.py.orig	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/setup.py.orig	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,21 @@
+from setuptools import setup, find_packages
+
+setup(
+    name='grok',
+    version='0.9',
+    author='Grok Team',
+    author_email='grok-dev at zope.org',
+    url='https://launchpad.net/grok',
+    download_url='svn://svn.zope.org/repos/main/grok/trunk#egg=grok-dev',
+    description='Grok: Now even cavemen can use Zope 3!',
+    long_description=open('README.txt').read(),
+    license='ZPL',
+
+    packages=find_packages('src'),
+    package_dir = {'': 'src'},
+    include_package_data = True,
+    zip_safe=False,    
+    install_requires=['setuptools',
+                      'martian',
+                      'simplejson'],
+)

Added: grok/branches/darrylcousins-martian-layers/src/grok/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Grok
+"""
+
+from zope.interface import implements
+from zope.component import adapts
+from zope.event import notify
+from zope.app.component.hooks import getSite
+from zope.lifecycleevent import (
+    IObjectCreatedEvent, ObjectCreatedEvent,
+    IObjectModifiedEvent, ObjectModifiedEvent,
+    IObjectCopiedEvent, ObjectCopiedEvent)
+
+from zope.app.container.contained import (
+    IObjectAddedEvent, ObjectAddedEvent,
+    IObjectMovedEvent, ObjectMovedEvent,
+    IObjectRemovedEvent, ObjectRemovedEvent,
+    IContainerModifiedEvent, ContainerModifiedEvent)
+
+from martian import ClassGrokker, InstanceGrokker, GlobalGrokker
+from grok.components import Model, Adapter, MultiAdapter, View, XMLRPC, JSON
+from grok.components import PageTemplate, PageTemplateFile, Container, Traverser
+from grok.components import Site, GlobalUtility, LocalUtility, Annotation
+from grok.components import Application, Form, AddForm, EditForm, DisplayForm
+from grok.components import Indexes, Skin, ILayer
+from grok.directive import (context, name, template, templatedir, provides,
+                            baseclass, global_utility, local_utility,
+                            define_permission, require, site, layer)
+from grok._grok import do_grok as grok  # Avoid name clash within _grok
+from grok._grok import grok_component
+from grok._grok import SubscribeDecorator as subscribe
+from martian.error import GrokError, GrokImportError
+from grok.formlib import action, AutoFields, Fields
+from grok.util import url
+
+# Our __init__ provides the grok API directly so using 'import grok' is enough.
+from grok.interfaces import IGrokAPI
+from zope.interface import moduleProvides
+moduleProvides(IGrokAPI)
+__all__ = list(IGrokAPI)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/_grok.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/_grok.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/_grok.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,139 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Grok
+"""
+import os
+import sys
+
+from zope import component
+from zope import interface
+
+from zope.component.interfaces import IDefaultViewName
+from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.app.component.site import LocalSiteManager
+
+import martian
+from martian import scan
+from martian.error import GrokError, GrokImportError
+from martian.util import frame_is_module, determine_module_context
+
+import grok
+
+from grok import components, meta
+from grok import templatereg
+
+_bootstrapped = False
+def bootstrap():
+    component.provideAdapter(components.ModelTraverser)
+    component.provideAdapter(components.ContainerTraverser)
+
+    # register the name 'index' as the default view name
+    component.provideAdapter('index',
+                             adapts=(grok.Model, IBrowserRequest),
+                             provides=IDefaultViewName)
+    component.provideAdapter('index',
+                             adapts=(grok.Container, IBrowserRequest),
+                             provides=IDefaultViewName)
+    # register a subscriber for when grok.Sites are added to make them
+    # into Zope 3 sites
+    component.provideHandler(
+        addSiteHandler, adapts=(grok.Site, grok.IObjectAddedEvent))
+
+    # now grok the grokkers
+    martian.grok_module(scan.module_info_from_module(meta), the_module_grokker)
+   
+def addSiteHandler(site, event):
+    sitemanager = LocalSiteManager(site)
+    # LocalSiteManager creates the 'default' folder in its __init__.
+    # It's not needed anymore in new versions of Zope 3, therefore we
+    # remove it
+    del sitemanager['default']
+    site.setSiteManager(sitemanager)
+
+# add a cleanup hook so that grok will bootstrap itself again whenever
+# the Component Architecture is torn down.
+def resetBootstrap():
+    global _bootstrapped
+    # we need to make sure that the grokker registry is clean again
+    the_module_grokker.clear()
+    _bootstrapped = False
+from zope.testing.cleanup import addCleanUp
+addCleanUp(resetBootstrap)
+
+
+def do_grok(dotted_name):
+    global _bootstrapped
+    if not _bootstrapped:
+        bootstrap()
+        _bootstrapped = True
+    martian.grok_dotted_name(dotted_name, the_module_grokker)
+
+def grok_component(name, component,
+                   context=None, module_info=None, templates=None):
+    #import pdb; pdb.set_trace()
+    return the_multi_grokker.grok(name, component,
+                                  context=context,
+                                  module_info=module_info,
+                                  templates=templates)
+
+def prepare_grok(name, module, kw):
+    module_info = scan.module_info_from_module(module)
+    
+    # XXX hardcoded in here which base classes are possible contexts
+    # this should be made extensible
+    possible_contexts = martian.scan_for_classes(module, [grok.Model,
+                                                          grok.LocalUtility,
+                                                          grok.Container])
+    context = determine_module_context(module_info, possible_contexts)
+    
+    kw['context'] = context    
+    kw['module_info'] = module_info
+    kw['templates'] = templatereg.TemplateRegistry()
+
+def finalize_grok(name, module, kw):
+    module_info = kw['module_info']
+    templates = kw['templates']
+    unassociated = list(templates.listUnassociated())
+    if unassociated:
+        raise GrokError("Found the following unassociated template(s) when "
+                        "grokking %r: %s.  Define view classes inheriting "
+                        "from grok.View to enable the template(s)."
+                        % (module_info.dotted_name,
+                           ', '.join(unassociated)), module_info)
+
+the_multi_grokker = martian.MetaMultiGrokker()
+the_module_grokker = martian.ModuleGrokker(the_multi_grokker,
+                                           prepare=prepare_grok,
+                                           finalize=finalize_grok)
+
+# decorators
+class SubscribeDecorator:
+
+    def __init__(self, *args):
+        self.subscribed = args
+
+    def __call__(self, function):
+        frame = sys._getframe(1)
+        if not frame_is_module(frame):
+            raise GrokImportError("@grok.subscribe can only be used on module "
+                                  "level.")
+
+        if not self.subscribed:
+            raise GrokImportError("@grok.subscribe requires at least one "
+                                  "argument.")
+
+        subscribers = frame.f_locals.get('__grok_subscribers__', None)
+        if subscribers is None:
+            frame.f_locals['__grok_subscribers__'] = subscribers = []
+        subscribers.append((function, self.subscribed))


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/_grok.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/admin/README.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/admin/README.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/admin/README.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,13 @@
+A basic grok admin UI
+====================
+
+Overview
+--------
+
+* List of all instanciated applications (grouped by application?)
+
+* "Add new application" form: drop down for selecting the application
+   and a field for the id.
+
+* "Delete application" form: checkboxes displayed with listed installed
+  applications. Selected items may be deleted.


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/admin/README.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/src/grok/admin/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/admin/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/admin/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#make this a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/admin/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/admin/view.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/admin/view.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/admin/view.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,36 @@
+import zope.component
+import grok.interfaces
+from zope.app.folder.interfaces import IRootFolder
+
+grok.context(IRootFolder)
+grok.define_permission('grok.ManageApplications')
+
+class Index(grok.View):
+    grok.name('index.html') # the root folder isn't a grok.Model
+    grok.require('grok.ManageApplications')
+
+    def update(self):
+        apps = zope.component.getAllUtilitiesRegisteredFor(
+            grok.interfaces.IApplication)
+        self.applications = ("%s.%s" % (x.__module__, x.__name__)
+                             for x in apps)
+
+class Add(grok.View):
+    grok.require('grok.ManageApplications')
+
+    def render(self, application, name):
+        app = zope.component.getUtility(grok.interfaces.IApplication,
+                                        name=application)
+        self.context[name] = app()
+        self.redirect(self.url(self.context))
+
+class Delete(grok.View):
+    grok.require('grok.ManageApplications')
+
+    def render(self, items):
+        if not isinstance(items, list):
+            items = [items]
+        for name in items:
+            del self.context[name]
+        self.redirect(self.url(self.context))
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/admin/view.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/admin/view_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/admin/view_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/admin/view_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,50 @@
+<html>
+  <head>
+    <title>grok administration interface</title>
+  </head>
+
+  <body tal:define="apps context/values">
+    <h1>Grok Applications</h1>
+
+    <form tal:attributes="action string:${context/@@absolute_url}/delete"
+          tal:condition="apps|nothing">
+      <fieldset>
+        <legend>Installed applications</legend>
+
+    <ul>
+      <li tal:repeat="app apps">
+        <input type="checkbox" tal:attributes="value app/__name__;
+                                               name string:items" />
+        <a tal:attributes="href string:${context/@@absolute_url}/${app/__name__}">
+          <span tal:replace="app/__name__"/>
+          (<span tal:replace="app/__class__/__name__"/>)
+        </a>
+      </li>
+    </ul>
+
+        <p><input type="submit" value="Delete Selected"/></p>
+        </fieldset>
+    </form>
+    <form tal:attributes="action string:${context/@@absolute_url}/add">
+      <fieldset>
+        <legend>Add application</legend>
+
+        <p>
+          <label>Application: 
+            <select height="1" name="application"> 
+              <option tal:repeat="app view/applications" 
+                tal:attributes="value app" 
+                tal:content="app"
+                />
+            </select> 
+          </label>
+        </p>
+
+        <p><label>Name: <input type="text" name="name"/></label></p>
+
+        <p><input type="submit" value="Add"/></p>
+
+      </fieldset>
+    </form>
+  </body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/src/grok/components.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/components.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/components.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,474 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Grok components
+"""
+
+import os
+import persistent
+import urllib
+import datetime
+import warnings
+import pytz
+import simplejson
+
+from zope import component
+from zope import interface
+from zope import schema
+from zope import event
+from zope.interface.common import idatetime
+from zope.lifecycleevent import ObjectModifiedEvent
+from zope.publisher.browser import BrowserPage
+from zope.publisher.interfaces import NotFound
+from zope.publisher.interfaces.browser import (IBrowserPublisher,
+                                               IDefaultBrowserLayer,
+                                               IBrowserRequest)
+from zope.publisher.publish import mapply
+from zope.pagetemplate import pagetemplate, pagetemplatefile
+from zope.formlib import form
+from zope.traversing.browser.interfaces import IAbsoluteURL
+from zope.traversing.browser.absoluteurl import AbsoluteURL
+from zope.traversing.browser.absoluteurl import _safe as SAFE_URL_CHARACTERS
+from zope.annotation.interfaces import IAttributeAnnotatable
+
+from zope.app.pagetemplate.engine import TrustedAppPT
+from zope.app.publisher.browser import getDefaultViewName
+from zope.app.publisher.browser import directoryresource
+from zope.app.publisher.browser.pagetemplateresource import \
+    PageTemplateResourceFactory
+from zope.app.container.btree import BTreeContainer
+from zope.app.container.contained import Contained
+from zope.app.container.interfaces import IReadContainer
+from zope.app.component.site import SiteManagerContainer
+
+from martian import util
+
+from grok import interfaces, formlib
+from grok.util import url
+
+class Model(Contained, persistent.Persistent):
+    # XXX Inheritance order is important here. If we reverse this,
+    # then containers can't be models anymore because no unambigous MRO
+    # can be established.
+    interface.implements(IAttributeAnnotatable)
+
+
+class Container(BTreeContainer):
+    interface.implements(IAttributeAnnotatable)
+
+
+class Site(SiteManagerContainer):
+    pass
+
+
+class Application(Site):
+    """A top-level application object."""
+    interface.implements(interfaces.IApplication)
+
+class Adapter(object):
+
+    def __init__(self, context):
+        self.context = context
+
+
+class GlobalUtility(object):
+    pass
+
+
+class LocalUtility(Model):
+    pass
+
+
+class MultiAdapter(object):
+    pass
+
+
+class Annotation(persistent.Persistent):
+    pass
+
+
+class View(BrowserPage):
+    interface.implements(interfaces.IGrokView)
+
+    def __init__(self, context, request):
+        super(View, self).__init__(context, request)
+        self.static = component.queryAdapter(
+            self.request,
+            interface.Interface,
+            name=self.module_info.package_dotted_name
+            )
+
+    @property
+    def response(self):
+        return self.request.response
+
+    def __call__(self):
+        mapply(self.update, (), self.request)
+        if self.request.response.getStatus() in (302, 303):
+            # A redirect was triggered somewhere in update().  Don't
+            # continue rendering the template or doing anything else.
+            return
+
+        template = getattr(self, 'template', None)
+        if template is not None:
+            return self._render_template()
+        return mapply(self.render, (), self.request)
+
+    def _render_template(self):
+        namespace = self.template.pt_getContext()
+        namespace['request'] = self.request
+        namespace['view'] = self
+        namespace['context'] = self.context
+        # XXX need to check whether we really want to put None here if missing
+        namespace['static'] = self.static
+        return self.template.pt_render(namespace)
+
+    def __getitem__(self, key):
+        # XXX give nice error message if template is None
+        return self.template.macros[key]
+
+    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 url(self.request, obj, name)
+
+    def application_url(self, name=None):
+        obj = self.context
+        while obj is not None:
+            if isinstance(obj, Application):
+                return self.url(obj, name)
+            obj = obj.__parent__
+        raise ValueError("No application found.")
+
+    def redirect(self, url):
+        return self.request.response.redirect(url)
+
+    def update(self):
+        pass
+
+class GrokViewAbsoluteURL(AbsoluteURL):
+
+    def _getContextName(self, context):
+        return getattr(context, '__view_name__', None)
+    # XXX breadcrumbs method on AbsoluteURL breaks as it does not use
+    # _getContextName to get to the name of the view. What does breadcrumbs do?
+
+
+class XMLRPC(object):
+    pass
+
+class JSON(BrowserPage):
+
+    def __call__(self):
+        view_name = self.__view_name__
+        method = getattr(self, view_name)
+        method_result = mapply(method, (), self.request)
+        return simplejson.dumps(method_result)
+
+class GrokPageTemplate(object):
+
+    def __repr__(self):
+        return '<%s template in %s>' % (self.__grok_name__,
+                                        self.__grok_location__)
+
+    def _annotateGrokInfo(self, name, location):
+        self.__grok_name__ = name
+        self.__grok_location__ = location
+
+
+class PageTemplate(GrokPageTemplate, TrustedAppPT, pagetemplate.PageTemplate):
+    expand = 0
+
+    def __init__(self, template):
+        super(PageTemplate, self).__init__()
+        if util.not_unicode_or_ascii(template):
+            raise ValueError("Invalid page template. Page templates must be "
+                             "unicode or ASCII.")
+        self.write(template)
+
+        # __grok_module__ is needed to make defined_locally() return True for
+        # inline templates
+        # XXX unfortunately using caller_module means that
+        # PageTemplate cannot be subclassed
+        self.__grok_module__ = util.caller_module()
+
+
+class PageTemplateFile(GrokPageTemplate, TrustedAppPT,
+                       pagetemplatefile.PageTemplateFile):
+
+    def __init__(self, filename, _prefix=None):
+        _prefix = self.get_path_from_prefix(_prefix)
+        super(PageTemplateFile, self).__init__(filename, _prefix)
+
+        # __grok_module__ is needed to make defined_locally() return True for
+        # inline templates
+        # XXX unfortunately using caller_module means that
+        # PageTemplateFile cannot be subclassed
+        self.__grok_module__ = util.caller_module()
+
+
+class DirectoryResource(directoryresource.DirectoryResource):
+    # We subclass this, because we want to override the default factories for
+    # the resources so that .pt and .html do not get created as page
+    # templates
+
+    resource_factories = {}
+    for type, factory in (directoryresource.DirectoryResource.
+                          resource_factories.items()):
+        if factory is PageTemplateResourceFactory:
+            continue
+        resource_factories[type] = factory
+
+
+class DirectoryResourceFactory(object):
+    # We need this to allow hooking up our own GrokDirectoryResource
+    # and to set the checker to None (until we have our own checker)
+
+    def __init__(self, path, name):
+        # XXX we're not sure about the checker=None here
+        self.__dir = directoryresource.Directory(path, None, name)
+        self.__name = name
+
+    def __call__(self, request):
+        resource = DirectoryResource(self.__dir, request)
+        resource.__name__ = self.__name
+        return resource
+
+
+class Traverser(object):
+    interface.implements(IBrowserPublisher)
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    def browserDefault(self, request):
+        view_name = getDefaultViewName(self.context, request)
+        view_uri = "@@%s" % view_name
+        return self.context, (view_uri,)
+
+    def publishTraverse(self, request, name):
+        subob = self.traverse(name)
+        if subob is not None:
+            return subob
+
+        # XXX Special logic here to deal with containers.  It would be
+        # good if we wouldn't have to do this here. One solution is to
+        # rip this out and make you subclass ContainerTraverser if you
+        # wanted to override the traversal behaviour of containers.
+        if IReadContainer.providedBy(self.context):
+            item = self.context.get(name)
+            if item is not None:
+                return item
+
+        view = component.queryMultiAdapter((self.context, request), name=name)
+        if view is not None:
+            return view
+
+        raise NotFound(self.context, name, request)
+
+    def traverse(self, name):
+        # this will be overridden by subclasses
+        pass
+
+
+class ModelTraverser(Traverser):
+    component.adapts(Model, IBrowserRequest)
+
+    def traverse(self, name):
+        traverse = getattr(self.context, 'traverse', None)
+        if traverse:
+            return traverse(name)
+
+
+class ContainerTraverser(Traverser):
+    component.adapts(Container, IBrowserRequest)
+
+    def traverse(self, name):
+        traverse = getattr(self.context, 'traverse', None)
+        if traverse:
+            result = traverse(name)
+            if result is not None:
+                return result
+        # try to get the item from the container
+        return self.context.get(name)
+
+default_form_template = PageTemplateFile(os.path.join(
+    'templates', 'default_edit_form.pt'))
+default_form_template.__grok_name__ = 'default_edit_form'
+default_display_template = PageTemplateFile(os.path.join(
+    'templates', 'default_display_form.pt'))
+default_display_template.__grok_name__ = 'default_display_form'
+
+class GrokForm(object):
+    """Mix-in to console zope.formlib's forms with grok.View and to
+    add some more useful methods.
+
+    The consolation needs to happen because zope.formlib's Forms have
+    update/render methods which have different meanings than
+    grok.View's update/render methods.  We deal with this issue by
+    'renaming' zope.formlib's update() to update_form() and by
+    disallowing subclasses to have custom render() methods."""
+
+    def update(self):
+        """Subclasses can override this method just like on regular
+        grok.Views. It will be called before any form processing
+        happens."""
+
+    def update_form(self):
+        """Update the form, i.e. process form input using widgets.
+
+        On zope.formlib forms, this is what the update() method is.
+        In grok views, the update() method has a different meaning.
+        That's why this method is called update_form() in grok forms."""
+        super(GrokForm, self).update()
+
+    def render(self):
+        """Render the form, either using the form template or whatever
+        the actions returned in form_result."""
+        # if the form has been updated, it will already have a result
+        if self.form_result is None:
+            if self.form_reset:
+                # we reset, in case data has changed in a way that
+                # causes the widgets to have different data
+                self.resetForm()
+                self.form_reset = False
+            self.form_result = self._render_template()
+
+        return self.form_result
+
+    # Mark the render() method as a method from the base class. That
+    # way we can detect whether somebody overrides render() in a
+    # subclass (which we don't allow).
+    render.base_method = True
+
+    def __call__(self):
+        mapply(self.update, (), self.request)
+        if self.request.response.getStatus() in (302, 303):
+            # A redirect was triggered somewhere in update().  Don't
+            # continue rendering the template or doing anything else.
+            return
+
+        self.update_form()
+        return self.render()
+
+class Form(GrokForm, form.FormBase, View):
+    # We're only reusing the form implementation from zope.formlib, we
+    # explicitly don't want to inherit the interface semantics (mostly
+    # for the different meanings of update/render).
+    interface.implementsOnly(interfaces.IGrokForm)
+
+    template = default_form_template
+
+    def applyData(self, obj, **data):
+        return formlib.apply_data_event(obj, self.form_fields, data,
+                                        self.adapters)
+
+    # BBB -- to be removed in June 2007
+    def applyChanges(self, obj, **data):
+        warnings.warn("The 'applyChanges' method on forms is deprecated "
+                      "and will disappear by June 2007. Please use "
+                      "'applyData' instead.", DeprecationWarning, 2)
+        return bool(self.applyData(obj, **data))
+
+class AddForm(Form):
+    pass
+
+class EditForm(GrokForm, form.EditFormBase, View):
+    # We're only reusing the form implementation from zope.formlib, we
+    # explicitly don't want to inherit the interface semantics (mostly
+    # for the different meanings of update/render).
+    interface.implementsOnly(interfaces.IGrokForm)
+
+    template = default_form_template
+
+    def applyData(self, obj, **data):
+        return formlib.apply_data_event(obj, self.form_fields, data,
+                                        self.adapters, update=True)
+
+    # BBB -- to be removed in June 2007
+    def applyChanges(self, obj, **data):
+        warnings.warn("The 'applyChanges' method on forms is deprecated "
+                      "and will disappear by June 2007. Please use "
+                      "'applyData' instead.", DeprecationWarning, 2)
+        return bool(self.applyData(obj, **data))
+
+    @formlib.action("Apply")
+    def handle_edit_action(self, **data):
+        if self.applyData(self.context, **data):
+            formatter = self.request.locale.dates.getFormatter(
+                'dateTime', 'medium')
+
+            try:
+                time_zone = idatetime.ITZInfo(self.request)
+            except TypeError:
+                time_zone = pytz.UTC
+
+            self.status = "Updated on %s" % formatter.format(
+                datetime.datetime.now(time_zone)
+                )
+        else:
+            self.status = 'No changes'
+
+class DisplayForm(GrokForm, form.DisplayFormBase, View):
+    # We're only reusing the form implementation from zope.formlib, we
+    # explicitly don't want to inherit the interface semantics (mostly
+    # for the different meanings of update/render).
+    interface.implementsOnly(interfaces.IGrokForm)
+
+    template = default_display_template
+
+class IndexesClass(object):
+    def __init__(self, name, bases=(), attrs=None):
+        if attrs is None:
+            return
+        # make sure we take over a bunch of possible attributes
+        for name in ['__grok_context__', '__grok_name__',
+                     '__grok_site__']:
+            value = attrs.get(name)
+            if value is not None:
+                setattr(self, name, value)
+        # now read and store indexes
+        indexes = {}
+        for name, value in attrs.items():
+            if not interfaces.IIndexDefinition.providedBy(value):
+                continue
+            indexes[name] = value
+        self.__grok_indexes__ = indexes
+        # __grok_module__ is needed to make defined_locally() return True for
+        # inline templates
+        self.__grok_module__ = util.caller_module()
+        
+Indexes = IndexesClass('Indexes')
+
+class ILayer(IDefaultBrowserLayer):
+    pass
+
+
+class Skin(object):
+    pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/components.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/configure.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/configure.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/configure.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,48 @@
+<configure    
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:grok="http://namespaces.zope.org/grok">
+
+  <!-- we register special IAbsoluteURL views on grok views so that
+       can have them inspect __view_name__ instead of __name__.  
+       __name__ is already used as the class name, and overriding it
+       may make error messages more confusing.  -->
+
+  <view
+      for=".interfaces.IGrokView"
+      name="absolute_url"
+      factory=".components.GrokViewAbsoluteURL"
+      type="zope.publisher.interfaces.http.IHTTPRequest"
+      permission="zope.Public"
+      allowed_interface="zope.traversing.browser.interfaces.IAbsoluteURL"
+      />
+
+  <view
+      for=".interfaces.IGrokView"
+      factory=".components.GrokViewAbsoluteURL"
+      type="zope.publisher.interfaces.http.IHTTPRequest"
+      permission="zope.Public"
+      provides="zope.traversing.browser.interfaces.IAbsoluteURL"
+      />
+
+  <!-- this overrides Zope 3's publication factories because they have
+       the same name; we also need to change the priority because of
+       the ZCML discriminator -->
+  <publisher
+      name="XMLRPC"
+      factory=".publication.GrokXMLRPCFactory"
+      methods="POST"
+      mimetypes="text/xml"
+      priority="21"
+      />
+
+  <publisher
+      name="BROWSER"
+      factory=".publication.GrokBrowserFactory"
+      methods="GET POST HEAD"
+      mimetypes="*"
+      priority="11"
+      />
+
+  <grok:grok package=".admin" />
+
+</configure>

Added: grok/branches/darrylcousins-martian-layers/src/grok/directive.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/directive.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/directive.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,114 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Grok directives.
+"""
+
+from zope.interface.interfaces import IInterface
+
+from martian.error import GrokImportError
+from martian.directive import (MultipleTimesDirective, BaseTextDirective,
+                               SingleValue, SingleTextDirective,
+                               MultipleTextDirective,
+                               MarkerDirective,
+                               InterfaceDirective,
+                               InterfaceOrClassDirective,
+                               ModuleDirectiveContext,
+                               ClassDirectiveContext,
+                               ClassOrModuleDirectiveContext)
+from martian import util
+
+class GlobalUtilityDirective(MultipleTimesDirective):
+    def check_arguments(self, factory, provides=None, name=u'',
+                        direct=False):
+        if provides is not None and not IInterface.providedBy(provides):
+            raise GrokImportError("You can only pass an interface to the "
+                                  "provides argument of %s." % self.name)
+
+    def value_factory(self, *args, **kw):
+        return GlobalUtilityInfo(*args, **kw)
+
+
+class GlobalUtilityInfo(object):
+    def __init__(self, factory, provides=None, name=u'', direct=False):
+        self.factory = factory
+        self.direct = direct
+
+        if provides is None:
+            provides = util.class_annotation(factory, 'grok.provides', None)
+        self.provides = provides
+        
+        if name is u'':
+            name = util.class_annotation(factory, 'grok.name', u'')
+        self.name = name
+
+
+class LocalUtilityDirective(MultipleTimesDirective):
+    def check_arguments(self, factory, provides=None, name=u'',
+                        setup=None, public=False, name_in_container=None):
+        if provides is not None and not IInterface.providedBy(provides):
+            raise GrokImportError("You can only pass an interface to the "
+                                  "provides argument of %s." % self.name)
+
+    def value_factory(self, *args, **kw):
+        return LocalUtilityInfo(*args, **kw)
+
+
+class LocalUtilityInfo(object):
+    def __init__(self, factory, provides=None, name=u'',
+                 setup=None, public=False, name_in_container=None):
+        self.factory = factory
+        if provides is None:
+            provides = util.class_annotation(factory, 'grok.provides', None)
+        self.provides = provides
+        self.name = name
+        self.setup = setup
+        self.public = public
+        self.name_in_container = name_in_container
+
+
+class RequireDirective(BaseTextDirective, SingleValue, MultipleTimesDirective):
+
+    def store(self, frame, value):
+        super(RequireDirective, self).store(frame, value)
+        values = frame.f_locals.get(self.local_name, [])
+
+        # grok.require can be used both as a class-level directive and
+        # as a decorator for methods.  Therefore we return a decorator
+        # here, which may be used for methods, or simply ignored when
+        # used as a directive.
+        def decorator(func):
+            permission = values.pop()
+            func.__grok_require__ = permission
+            return func
+        return decorator
+
+# Define grok directives
+name = SingleTextDirective('grok.name', ClassDirectiveContext())
+template = SingleTextDirective('grok.template', ClassDirectiveContext())
+context = InterfaceOrClassDirective('grok.context',
+                                    ClassOrModuleDirectiveContext())
+templatedir = SingleTextDirective('grok.templatedir', ModuleDirectiveContext())
+provides = InterfaceDirective('grok.provides', ClassDirectiveContext())
+baseclass = MarkerDirective('grok.baseclass', ClassDirectiveContext())
+global_utility = GlobalUtilityDirective('grok.global_utility',
+                                        ModuleDirectiveContext())
+local_utility = LocalUtilityDirective('grok.local_utility',
+                                      ClassDirectiveContext())
+define_permission = MultipleTextDirective('grok.define_permission',
+                                          ModuleDirectiveContext())
+require = RequireDirective('grok.require', ClassDirectiveContext())
+site = InterfaceOrClassDirective('grok.site',
+                                 ClassDirectiveContext())
+layer = InterfaceOrClassDirective('grok.layer',
+                           ClassOrModuleDirectiveContext())


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/directive.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/formlib.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/formlib.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/formlib.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,147 @@
+import types
+from zope import interface, event, lifecycleevent
+from zope.interface.interfaces import IInterface
+from zope.formlib import form
+from zope.schema.interfaces import IField
+
+class action(form.action):
+    """We override the action decorator we pass in our custom Action.
+    """
+    def __call__(self, success):
+        action = Action(self.label, success=success, **self.options)
+        self.actions.append(action)
+        return action
+
+class Action(form.Action):
+    def success(self, data):
+        if self.success_handler is not None:
+            return self.success_handler(self.form, **data)
+
+def Fields(*args, **kw):
+    fields = []
+    for key, value in kw.items():
+        if IField.providedBy(value):
+            value.__name__ = key
+            fields.append(value)
+            del kw[key]
+    fields.sort(key=lambda field: field.order)
+    return form.Fields(*(args + tuple(fields)), **kw)
+
+def get_context_schema_fields(context):
+    """Get the schema fields for a context object.
+    """
+    fields = []
+    fields_class = getattr(context, 'fields', None)
+    # bail out if there is no fields attribute at all
+    if fields_class is None:
+        return fields
+    # bail out if there's a fields attribute but it isn't an old-style class
+    if type(fields_class) != types.ClassType:
+        return fields
+    # get the fields from the class
+    for name in dir(fields_class):
+        field = getattr(fields_class, name)
+        if IField.providedBy(field):
+            if not getattr(field, '__name__', None):
+                field.__name__ = name
+            fields.append(field)
+    fields.sort(key=lambda field: field.order)
+    return fields
+
+def get_auto_fields(context):
+    """Get the form fields for context.
+    """
+    # for an interface context, we generate them from that interface
+    if IInterface.providedBy(context):
+        return form.Fields(context)
+    # if we have a non-interface context,
+    # we're autogenerating them from any model-specific
+    # fields along with any schemas defined by the context
+    fields = form.Fields(*get_context_schema_fields(context))
+    fields += form.Fields(*most_specialized_interfaces(context))
+    # we pull in this field by default, but we don't want it in our form
+    fields = fields.omit('__name__')
+    return fields
+
+AutoFields = get_auto_fields
+
+def most_specialized_interfaces(context):
+    """Get interfaces for an object without any duplicates.
+
+    Interfaces in a declaration for an object may already have been seen
+    because it is also inherited by another interface. Don't return the
+    interface twice, as that would result in duplicate names when creating
+    the form.
+    """
+    declaration = interface.implementedBy(context)
+    seen = []
+    for iface in declaration.flattened():
+        if interface_seen(seen, iface):
+            continue
+        seen.append(iface)
+    return seen
+
+def interface_seen(seen, iface):
+    """Return True if interface already is seen.
+    """
+    for seen_iface in seen:
+        if seen_iface.extends(iface):
+            return True
+    return False
+
+def apply_data(context, form_fields, data, adapters=None, update=False):
+    """Save form data (``data`` dict) on a ``context`` object.
+
+    This is a beefed up version of zope.formlib.form.applyChanges().
+    It allows you to specify whether values should be compared with
+    the attributes on already existing objects or not, using the
+    ``update`` parameter.
+
+    Unlike zope.formlib.form.applyChanges(), it will return a
+    dictionary of interfaces and their fields that were changed.  This
+    is necessary to appropriately send IObjectModifiedEvents.
+    """
+    if adapters is None:
+        adapters = {}
+
+    changes = {}
+
+    for form_field in form_fields:
+        field = form_field.field
+        # Adapt context, if necessary
+        interface = field.interface
+        adapter = adapters.get(interface)
+        if adapter is None:
+            if interface is None:
+                adapter = context
+            else:
+                adapter = interface(context)
+            adapters[interface] = adapter
+
+        name = form_field.__name__
+        newvalue = data.get(name, form_field) # using form_field as marker
+
+        if update:
+            if ((newvalue is not form_field) and
+                (field.get(adapter) != newvalue)):
+                field.set(adapter, newvalue)
+                changes.setdefault(interface, []).append(name)
+        else:
+            if newvalue is not form_field:
+                field.set(adapter, newvalue)
+                changes.setdefault(interface, []).append(name)
+
+    return changes
+
+def apply_data_event(context, form_fields, data, adapters=None, update=False):
+    """Like apply_data, but also sends an IObjectModifiedEvent.
+    """
+    changes = apply_data(context, form_fields, data, adapters, update)
+
+    if changes:
+        descriptions = []
+        for interface, names in changes.items():
+            descriptions.append(lifecycleevent.Attributes(interface, *names))
+        event.notify(lifecycleevent.ObjectModifiedEvent(context, *descriptions))
+
+    return changes


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/formlib.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/README.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/README.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/README.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,6 @@
+Creating functional tests
+-------------------------
+
+Unfortunately, functional doctests do not import themselves (as the
+unit-test ones do), so you need to manually import the module in the
+doctest part.


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/README.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/admin/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/admin/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/admin/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/admin/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/admin/admin.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/admin/admin.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/admin/admin.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,59 @@
+"""
+  >>> import grok
+  >>> grok.grok('grok.ftests.admin.admin')
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/")
+  >>> print browser.contents
+  <html>
+  ...
+  ...<legend>Add application</legend>
+  ...
+  >>> browser.getControl('Application').displayValue = ['grok.ftests.admin.admin.MammothManager']
+  >>> browser.getControl('Name').value = 'my-mammoth-manager'
+  >>> browser.getControl('Add').click()
+  >>> print browser.contents
+  <html>
+  ...
+      <li>
+        <input type="checkbox" name="items" value="my-mammoth-manager" />
+        <a href="http://localhost/my-mammoth-manager">
+          my-mammoth-manager
+          (MammothManager)
+        </a>
+      </li>
+  ...
+  >>> browser.getLink('my-mammoth-manager').click()
+  >>> print browser.contents
+  Let's manage some mammoths!
+
+We are able to delete installed applications.
+
+  >>> browser.open("http://localhost/")
+  >>> print browser.contents
+  <html>
+  ...
+  ...<legend>Installed applications</legend>
+  ...
+  >>> ctrl = browser.getControl(name='items')
+  >>> ctrl.getControl(value='my-mammoth-manager').selected = True
+  >>> browser.getControl('Delete Selected').click()
+  >>> print browser.contents
+  <html>
+  ...
+  ...<legend>Add application</legend>
+  ...
+
+"""
+import grok
+
+class MammothManager(grok.Application, grok.Container):
+    pass
+
+class Index(grok.View):
+
+    def render(self):
+        return u"Let's manage some mammoths!"


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/admin/admin.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# make this directory a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/catalog.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/catalog.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/catalog.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,52 @@
+"""
+  >>> import grok
+  >>> from grok.ftests.catalog.catalog import Mammoth, Herd
+  >>> grok.grok('grok.ftests.catalog.catalog')
+
+Let's setup a site in which we manage a couple of objects:
+
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  >>> from zope.app.component.hooks import setSite
+  >>> setSite(herd)
+
+Now we add some indexable objects to the site:
+
+  >>> herd['manfred'] = Mammoth('Manfred')
+  >>> herd['ellie'] = Mammoth('Ellie')
+
+Then we are able to query the catalog:
+
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.component import getUtility
+  >>> catalog = getUtility(ICatalog)
+  >>> for obj in catalog.searchResults(name=('Ellie', 'Ellie')):
+  ...     print obj.name
+  Ellie
+
+"""
+
+import grok
+from zope import schema, interface
+from zope.app.intid import IntIds
+from zope.app.intid.interfaces import IIntIds
+from zope.app.catalog.catalog import Catalog
+from zope.app.catalog.interfaces import ICatalog
+from zope.app.catalog.field import FieldIndex
+
+def setup_catalog(catalog):
+    catalog['name'] = FieldIndex('name', IMammoth)
+
+class IMammoth(interface.Interface):
+
+    name = schema.TextLine()
+
+class Mammoth(grok.Model):
+    grok.implements(IMammoth)
+
+    def __init__(self, name):
+        self.name = name
+
+class Herd(grok.Container, grok.Site):
+    grok.local_utility(IntIds, provides=IIntIds)
+    grok.local_utility(Catalog, provides=ICatalog, setup=setup_catalog)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/catalog.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,105 @@
+"""
+Grok allows you to set up catalog indexes in your application with a
+special indexes declaration.
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.catalog.indexes')
+
+Let's set up a site in which we manage a couple of objects::
+
+  >>> from grok.ftests.catalog.indexes import Herd, Herd2, Mammoth
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  >>> from zope.app.component.hooks import setSite
+  >>> setSite(herd)
+
+Now we add some indexable objects to the site::
+
+  >>> herd['alpha'] = Mammoth('Alpha', 13, 'Hello world!')
+  >>> herd['beta'] = Mammoth('Beta', 14, 'Bye World!')
+
+We are able to query the catalog::
+
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.component import getUtility, queryUtility
+  >>> catalog = getUtility(ICatalog)
+  >>> for obj in catalog.searchResults(name=('Beta', 'Beta')):
+  ...   print obj.name
+  Beta
+
+Let's query the text index, which incidentally also indexes a method::
+
+  >>> def sortedResults(catalog, **kw):
+  ...    result = list(catalog.searchResults(**kw))
+  ...    result.sort(key=lambda x:x.name)
+  ...    return [item.name for item in result]
+  >>> sortedResults(catalog, message='world')
+  ['Alpha', 'Beta']
+  >>> sortedResults(catalog, message='hello')
+  ['Alpha']
+  >>> sortedResults(catalog, message='bye')
+  ['Beta']
+
+Note that another application that we did not register the
+indexes for won't have a catalog available::
+
+  >>> herd2 = Herd2()
+  >>> getRootFolder()['herd2'] = herd2
+  >>> setSite(herd2)
+  >>> queryUtility(ICatalog, default=None) is None
+  True
+  >>> setSite(herd)
+  
+Nuke the catalog and intids in the end, so as not to confuse
+other tests::
+
+  >>> sm = herd.getSiteManager()
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> sm.unregisterUtility(catalog, provided=ICatalog)
+  True
+  >>> from zope.app.intid.interfaces import IIntIds
+  >>> from zope import component
+  >>> intids = component.getUtility(IIntIds)
+  >>> sm.unregisterUtility(intids, provided=IIntIds)
+  True
+
+Unfortunately ftests don't have good isolation from each other yet.
+"""
+
+from zope.interface import Interface
+from zope import schema
+
+import grok
+from grok import index
+
+class Herd(grok.Container, grok.Application):
+    pass
+
+class Herd2(grok.Container, grok.Application):
+    pass
+
+class IMammoth(Interface):
+    name = schema.TextLine(title=u'Name')
+    age = schema.Int(title=u'Age')
+    def message():
+        """Message the mammoth has for the world."""
+
+class MammothIndexes(grok.Indexes):
+    grok.site(Herd)
+    grok.context(IMammoth)
+
+    name = index.Field()
+    age = index.Field()
+    message = index.Text()
+
+class Mammoth(grok.Model):
+    grok.implements(IMammoth)
+
+    def __init__(self, name, age, message):
+        self.name = name
+        self.age = age
+        self._message = message
+
+    def message(self):
+        return self._message
+    


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_app_interface.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_app_interface.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_app_interface.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,100 @@
+"""
+Grok allows you to set up catalog indexes in your application with a
+special indexes declaration. Here we see how we can register indexes for
+an interface instead of an application directly.
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.catalog.indexes_app_interface')
+
+Let's set up a site in which we manage a couple of objects::
+
+  >>> from grok.ftests.catalog.indexes_app_interface import Herd, Herd2, Mammoth
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  >>> from zope.app.component.hooks import setSite
+  >>> setSite(herd)
+
+We are able to find the catalog::
+
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.component import getUtility
+  >>> catalog = getUtility(ICatalog)
+  >>> catalog is not None
+  True
+  >>> catalog.get('name') is not None
+  True
+
+Nuke the catalog and intids for this site, so as not to confuse
+other tests::
+
+  >>> sm = herd.getSiteManager()
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> sm.unregisterUtility(catalog, provided=ICatalog)
+  True
+  >>> from zope.app.intid.interfaces import IIntIds
+  >>> from zope import component
+  >>> intids = component.getUtility(IIntIds)
+  >>> sm.unregisterUtility(intids, provided=IIntIds)
+  True
+
+Now let's create another application providing the same interface::
+
+  >>> herd2 = Herd2()
+  >>> getRootFolder()['herd2'] = herd2
+  >>> setSite(herd2)
+  >>> catalog = getUtility(ICatalog)
+  >>> catalog is not None
+  True
+  >>> catalog.get('name') is not None
+  True
+  
+Nuke the catalog and intids in the end, so as not to confuse
+other tests::
+
+  >>> sm = herd2.getSiteManager()
+  >>> sm.unregisterUtility(catalog, provided=ICatalog)
+  True
+  >>> intids = component.getUtility(IIntIds)
+  >>> sm.unregisterUtility(intids, provided=IIntIds)
+  True
+"""
+
+from zope.interface import Interface
+from zope import schema
+
+import grok
+from grok import index
+
+class IHerd(Interface):
+    pass
+
+class Herd(grok.Container, grok.Application):
+    grok.implements(IHerd)
+
+class Herd2(grok.Container, grok.Application):
+    grok.implements(IHerd)
+
+class IMammoth(Interface):
+    name = schema.TextLine(title=u'Name')
+    age = schema.Int(title=u'Age')
+    def message():
+        """Message the mammoth has for the world."""
+
+class MammothIndexes(grok.Indexes):
+    grok.site(IHerd)
+    grok.context(IMammoth)
+
+    name = index.Field()
+    age = index.Field()
+    message = index.Text()
+
+class Mammoth(grok.Model):
+    grok.implements(IMammoth)
+
+    def __init__(self, name, age, message):
+        self.name = name
+        self.age = age
+        self._message = message
+
+    def message(self):
+        return self._message


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_app_interface.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_attribute.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_attribute.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_attribute.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,71 @@
+"""
+Grok allows you to set up catalog indexes in your application with a
+special indexes declaration. If you want to name the index differently
+from the attribute, you can do so, by passing an explicit `attribute`
+keyword argument to the field.
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.catalog.indexes_attribute')
+
+Let's set up a site in which we manage a couple of objects::
+
+  >>> from grok.ftests.catalog.indexes_attribute import Herd, Mammoth
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  >>> from zope.app.component.hooks import setSite
+  >>> setSite(herd)
+
+Now we add some indexable objects to the site::
+
+  >>> herd['alpha'] = Mammoth('Alpha', 13)
+  >>> herd['beta'] = Mammoth('Beta', 14)
+
+We are able to query the catalog::
+
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.component import getUtility, queryUtility
+  >>> catalog = getUtility(ICatalog)
+  >>> for obj in catalog.searchResults(how_old=(13, 13)):
+  ...   print obj.name
+  Alpha
+
+Nuke the catalog and intids in the end, so as not to confuse
+other tests::
+
+  >>> sm = herd.getSiteManager()
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> sm.unregisterUtility(catalog, provided=ICatalog)
+  True
+  >>> from zope.app.intid.interfaces import IIntIds
+  >>> from zope import component
+  >>> intids = component.getUtility(IIntIds)
+  >>> sm.unregisterUtility(intids, provided=IIntIds)
+  True
+"""
+
+from zope.interface import Interface
+from zope import schema
+
+import grok
+from grok import index
+
+class Herd(grok.Container, grok.Application):
+    pass
+
+class IMammoth(Interface):
+    name = schema.TextLine(title=u'Name')
+    age = schema.Int(title=u'Age')
+
+class MammothIndexes(grok.Indexes):
+    grok.site(Herd)
+    grok.context(IMammoth)
+
+    name = index.Field()
+    how_old = index.Field(attribute='age')
+
+class Mammoth(grok.Model):
+    grok.implements(IMammoth)
+
+    def __init__(self, name, age):
+        self.name = name
+        self.age = age


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_attribute.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_class.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_class.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_class.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,81 @@
+"""
+Grok allows you to set up catalog indexes in your application with a
+special indexes declaration. This can also be done without explicit interface.
+The context of the indexes applies to a class in this case.
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.catalog.indexes_class')
+
+Let's set up a site in which we manage a couple of objects::
+
+  >>> from grok.ftests.catalog.indexes_class import Herd, Mammoth
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  >>> from zope.app.component.hooks import setSite
+  >>> setSite(herd)
+
+Now we add some indexable objects to the site::
+
+  >>> herd['alpha'] = Mammoth('Alpha', 13, 'Hello world!')
+  >>> herd['beta'] = Mammoth('Beta', 14, 'Bye World!')
+
+We are able to query the catalog::
+
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.component import getUtility
+  >>> catalog = getUtility(ICatalog)
+  >>> for obj in catalog.searchResults(name=('Beta', 'Beta')):
+  ...   print obj.name
+  Beta
+
+Let's query the text index, which incidentally also indexes a method::
+
+  >>> def sortedResults(catalog, **kw):
+  ...    result = list(catalog.searchResults(**kw))
+  ...    result.sort(key=lambda x:x.name)
+  ...    return [item.name for item in result]
+  >>> sortedResults(catalog, message='world')
+  ['Alpha', 'Beta']
+  >>> sortedResults(catalog, message='hello')
+  ['Alpha']
+  >>> sortedResults(catalog, message='bye')
+  ['Beta']
+  
+Nuke the catalog and intids in the end, so as not to confuse
+other tests::
+
+  >>> sm = herd.getSiteManager()
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> sm.unregisterUtility(catalog, provided=ICatalog)
+  True
+  >>> from zope.app.intid.interfaces import IIntIds
+  >>> from zope import component
+  >>> intids = component.getUtility(IIntIds)
+  >>> sm.unregisterUtility(intids, provided=IIntIds)
+  True
+
+Unfortunately ftests don't have good isolation from each other yet.
+"""
+import grok
+from grok import index
+
+class Herd(grok.Container, grok.Application):
+    pass
+
+class Mammoth(grok.Model):
+    def __init__(self, name, age, message):
+        self.name = name
+        self.age = age
+        self._message = message
+
+    def message(self):
+        return self._message
+
+class MammothIndexes(grok.Indexes):
+    grok.context(Mammoth)
+    grok.site(Herd)
+    
+    name = index.Field()
+    age = index.Field()
+    message = index.Text()
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_class.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_module.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_module.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_module.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,16 @@
+"""
+You can create an index on module level, but that should lead to a GrokError:
+
+  >>> import grok
+  >>> from grok.ftests.catalog.indexes_module import func
+  >>> func()
+  Traceback (most recent call last):
+    ...
+  GrokImportError: <class 'grok.index.Field'> can only be instantiated on
+  class level.
+"""
+from grok import index
+
+def func():
+    foo = index.Field()
+    


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_module.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_multiple.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_multiple.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_multiple.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,76 @@
+"""
+Grok allows you to set up catalog indexes in your application with a
+special indexes declaration. In fact, we have multiple grok.Indexes
+setting up more than one set of indexes in the same catalog.
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.catalog.indexes_multiple')
+
+Let's set up a site in which we manage a couple of objects::
+
+  >>> from grok.ftests.catalog.indexes_multiple import Herd
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  >>> from zope.app.component.hooks import setSite
+  >>> setSite(herd)
+
+We are able to query the catalog::
+
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.component import getUtility, queryUtility
+  >>> catalog = getUtility(ICatalog)
+  >>> sorted(catalog.keys())
+  [u'age', u'age2', u'message', u'message2', u'name', u'name2']
+  
+Nuke the catalog and intids in the end, so as not to confuse
+other tests::
+
+  >>> sm = herd.getSiteManager()
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> sm.unregisterUtility(catalog, provided=ICatalog)
+  True
+  >>> from zope.app.intid.interfaces import IIntIds
+  >>> from zope import component
+  >>> intids = component.getUtility(IIntIds)
+  >>> sm.unregisterUtility(intids, provided=IIntIds)
+  True
+
+Unfortunately ftests don't have good isolation from each other yet.
+"""
+
+from zope.interface import Interface
+from zope import schema
+
+import grok
+from grok import index
+
+class Herd(grok.Container, grok.Application):
+    pass
+
+class IMammoth(Interface):
+    name = schema.TextLine(title=u'Name')
+    age = schema.Int(title=u'Age')
+    def message():
+        """Message the mammoth has for the world."""
+
+class IMammoth2(Interface):
+    name2 = schema.TextLine(title=u'Name')
+    age2 = schema.Int(title=u'Age')
+    def message2():
+        """Message the mammoth has for the world."""
+
+class MammothIndexes(grok.Indexes):
+    grok.site(Herd)
+    grok.context(IMammoth)
+
+    name = index.Field()
+    age = index.Field()
+    message = index.Text()
+
+class MammothIndexes2(grok.Indexes):
+    grok.site(Herd)
+    grok.context(IMammoth2)
+
+    name2 = index.Field()
+    age2 = index.Field()
+    message2 = index.Text()


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_multiple.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_multiple_conflict.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_multiple_conflict.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_multiple_conflict.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,69 @@
+"""
+Grok allows you to set up catalog indexes in your application with a
+special indexes declaration. In fact, we have multiple grok.Indexes
+setting up more than one set of indexes in the same catalog. What if these
+indexes define the same names?
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.catalog.indexes_multiple_conflict')
+
+Let's set up a site in which we manage a couple of objects::
+
+  >>> from grok.ftests.catalog.indexes_multiple_conflict import Herd
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  Traceback (most recent call last):
+    ...
+  GrokError: grok.Indexes in module <module
+  'grok.ftests.catalog.indexes_multiple_conflict' from ...>
+  causes creation of catalog index 'name' in catalog u'', but an index
+  with that name is already present.
+
+  >>> from zope.app.component.hooks import setSite
+  >>> setSite(herd)
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.component import getUtility, queryUtility
+  >>> catalog = getUtility(ICatalog)
+
+Nuke the catalog and intids in the end, so as not to confuse
+other tests::
+
+  >>> sm = herd.getSiteManager()
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> sm.unregisterUtility(catalog, provided=ICatalog)
+  True
+  >>> from zope.app.intid.interfaces import IIntIds
+  >>> from zope import component
+  >>> intids = component.getUtility(IIntIds)
+  >>> sm.unregisterUtility(intids, provided=IIntIds)
+  True
+
+Unfortunately ftests don't have good isolation from each other yet.
+"""
+
+from zope.interface import Interface
+from zope import schema
+
+import grok
+from grok import index
+
+class Herd(grok.Container, grok.Application):
+    pass
+
+class IMammoth(Interface):
+    name = schema.TextLine(title=u'Name')
+
+class IMammoth2(Interface):
+    name = schema.TextLine(title=u'Name')
+
+class MammothIndexes(grok.Indexes):
+    grok.site(Herd)
+    grok.context(IMammoth)
+
+    name = index.Field()
+
+class MammothIndexes2(grok.Indexes):
+    grok.site(Herd)
+    grok.context(IMammoth2)
+
+    name = index.Field()


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_multiple_conflict.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_name.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_name.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_name.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,63 @@
+"""
+Grok allows you to set up catalog indexes in your application with a
+special indexes declaration. We can specify the catalog name using
+grok.name.
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.catalog.indexes_name')
+
+Let's set up a site in which we manage a couple of objects::
+
+  >>> from grok.ftests.catalog.indexes_name import Herd, Mammoth
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  >>> from zope.app.component.hooks import setSite
+  >>> setSite(herd)
+
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.component import getUtility
+
+We have to look up the catalog by name now::
+
+  >>> catalog = getUtility(ICatalog, 'foo_catalog')
+  >>> catalog
+  <zope.app.catalog.catalog.Catalog object at ...>
+
+Nuke the catalog and intids in the end, so as not to confuse
+other tests::
+
+  >>> sm = herd.getSiteManager()
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> sm.unregisterUtility(catalog, provided=ICatalog, name='foo_catalog')
+  True
+  >>> from zope.app.intid.interfaces import IIntIds
+  >>> from zope import component
+  >>> intids = component.getUtility(IIntIds)
+  >>> sm.unregisterUtility(intids, provided=IIntIds)
+  True
+
+Unfortunately ftests don't have good isolation from each other yet.
+"""
+import grok
+from grok import index
+
+class Herd(grok.Container, grok.Application):
+    pass
+
+class Mammoth(grok.Model):
+    def __init__(self, name, age, message):
+        self.name = name
+        self.age = age
+        self._message = message
+
+    def message(self):
+        return self._message
+
+class MammothIndexes(grok.Indexes):
+    grok.context(Mammoth)
+    grok.name('foo_catalog')
+    grok.site(Herd)
+    
+    name = index.Field()
+    age = index.Field()
+    message = index.Text()


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_name.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_no_app.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_no_app.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_no_app.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,30 @@
+"""
+Grok allows you to set up catalog indexes in your application with a
+special indexes declaration.  We do need to specify a site (such as
+the application) for the Indexes however, otherwise we get a GrokError:
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.catalog.indexes_no_app')
+  Traceback (most recent call last):
+    ...
+  GrokError: No site specified for grok.Indexes subclass in module
+  <module 'grok.ftests.catalog.indexes_no_app' from ...>.
+  Use grok.site() to specify.
+  
+"""
+import grok
+from grok import index
+
+class Herd(grok.Container, grok.Application):
+    pass
+
+class Mammoth(grok.Model):
+    pass
+
+class MammothIndexes(grok.Indexes):
+    grok.context(Mammoth)
+    grok.name('foo_catalog')
+    
+    name = index.Field()
+    age = index.Field()
+    message = index.Text()


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_no_app.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_nonexistent.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_nonexistent.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_nonexistent.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,65 @@
+"""
+Grok allows you to set up catalog indexes in your application with a
+special indexes declaration. Here we show what happens if you try
+to set up an index for an attribute that does not exist on the interface.
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.catalog.indexes_nonexistent')
+
+Let's set up a site in which we manage a couple of objects::
+
+  >>> from grok.ftests.catalog.indexes_nonexistent import Herd
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  Traceback (most recent call last):
+    ...
+  GrokError: grok.Indexes in <module
+  'grok.ftests.catalog.indexes_nonexistent' from ...>
+  refers to an attribute or method 'foo' on interface <InterfaceClass
+  grok.ftests.catalog.indexes_nonexistent.IMammoth>, but this does not
+  exist.
+
+Nuke the catalog and intids in the end, so as not to confuse
+other tests::
+
+  >>> from zope.app.component.hooks import setSite
+  >>> setSite(herd)
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.component import getUtility
+  >>> catalog = getUtility(ICatalog)
+
+
+  >>> sm = herd.getSiteManager()
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> sm.unregisterUtility(catalog, provided=ICatalog)
+  True
+  >>> from zope.app.intid.interfaces import IIntIds
+  >>> from zope import component
+  >>> intids = component.getUtility(IIntIds)
+  >>> sm.unregisterUtility(intids, provided=IIntIds)
+  True
+"""
+
+from zope.interface import Interface
+from zope import schema
+
+import grok
+from grok import index
+
+class Herd(grok.Container, grok.Application):
+    pass
+
+class IMammoth(Interface):
+    name = schema.TextLine(title=u'Name')
+    age = schema.Int(title=u'Age')
+    def message():
+        """Message the mammoth has for the world."""
+
+class MammothIndexes(grok.Indexes):
+    grok.site(Herd)
+    grok.context(IMammoth)
+
+    foo = index.Field()
+
+
+    


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_nonexistent.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_site.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_site.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_site.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,60 @@
+"""
+Grok allows you to set up catalog indexes in your application with a
+special indexes declaration. In fact, these indexes can be set up for
+any site::
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.catalog.indexes_site')
+
+Let's set up a site in which we manage a couple of objects::
+
+  >>> from grok.ftests.catalog.indexes_site import Herd
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  >>> from zope.app.component.hooks import setSite
+  >>> setSite(herd)
+
+The catalog is there in the site::
+
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.component import getUtility, queryUtility
+  >>> catalog = queryUtility(ICatalog, default=None)
+  >>> catalog is not None
+  True
+
+Nuke the catalog and intids in the end, so as not to confuse
+other tests::
+
+  >>> sm = herd.getSiteManager()
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> sm.unregisterUtility(catalog, provided=ICatalog)
+  True
+  >>> from zope.app.intid.interfaces import IIntIds
+  >>> from zope import component
+  >>> intids = component.getUtility(IIntIds)
+  >>> sm.unregisterUtility(intids, provided=IIntIds)
+  True
+"""
+
+from zope.interface import Interface
+from zope import schema
+
+import grok
+from grok import index
+
+class Herd(grok.Container, grok.Site):
+    pass
+
+class IMammoth(Interface):
+    name = schema.TextLine(title=u'Name')
+    age = schema.Int(title=u'Age')
+    def message():
+        """Message the mammoth has for the world."""
+
+class MammothIndexes(grok.Indexes):
+    grok.site(Herd)
+    grok.context(IMammoth)
+
+    name = index.Field()
+    age = index.Field()
+    message = index.Text()


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/indexes_site.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/setuporder.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/setuporder.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/setuporder.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,57 @@
+"""
+This is similar to catalog.py, except that the site uses a base class
+which also defines a local utility.
+
+  >>> import grok
+  >>> from grok.ftests.catalog.setuporder import Mammoth, Herd
+  >>> grok.grok('grok.ftests.catalog.setuporder')
+
+Let's setup a site in which we manage a couple of objects:
+
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  >>> from zope.app.component.hooks import setSite
+  >>> setSite(herd)
+
+Now we add some indexable objects to the site:
+
+  >>> herd['manfred'] = Mammoth('Manfred')
+  >>> herd['ellie'] = Mammoth('Ellie')
+
+Then we are able to query the catalog:
+
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.component import getUtility
+  >>> catalog = getUtility(ICatalog)
+  >>> for obj in catalog.searchResults(name=('Ellie', 'Ellie')):
+  ...     print obj.name
+  Ellie
+
+"""
+
+import grok
+from zope import schema, interface
+from zope.app.intid import IntIds
+from zope.app.intid.interfaces import IIntIds
+from zope.app.catalog.catalog import Catalog
+from zope.app.catalog.interfaces import ICatalog
+from zope.app.catalog.field import FieldIndex
+
+def setup_catalog(catalog):
+    catalog['name'] = FieldIndex('name', IMammoth)
+
+class IMammoth(interface.Interface):
+
+    name = schema.TextLine()
+
+class Mammoth(grok.Model):
+    grok.implements(IMammoth)
+
+    def __init__(self, name):
+        self.name = name
+
+class BaseHerd(grok.Container, grok.Site):
+    grok.local_utility(IntIds, provides=IIntIds)
+
+class Herd(BaseHerd):
+    grok.local_utility(Catalog, provides=ICatalog, setup=setup_catalog)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/catalog/setuporder.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/actions.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/actions.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/actions.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,77 @@
+"""
+Using the @grok.action decorator, different actions can be defined on
+a grok.Form. When @grok.action is used, the default behaviour (the
+'Apply' action) is not available anymore, but it can triggered
+manually by calling self.applyData(object, data).
+
+  >>> import grok
+  >>> from grok.ftests.form.actions import Mammoth
+  >>> grok.grok('grok.ftests.form.actions')
+  >>> getRootFolder()["manfred"] = Mammoth()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/manfred/@@edit")
+  >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
+  >>> browser.getControl(name="form.size").value = "Really big"
+  >>> browser.getControl("Apply").click()
+  >>> print browser.contents
+  <html>...
+  ...Modified!...
+  ...Manfred the Mammoth...
+  ...Really big...
+  ...
+
+Save again without any changes:
+
+  >>> browser.getControl("Apply").click()
+  >>> print browser.contents
+  <html>...
+  ...No changes!...
+  ...
+
+  >>> browser.open("http://localhost/manfred/@@edit")
+  >>> browser.getControl(name="form.name").value = "Manfred the Second"
+  >>> browser.getControl("Hairy").click()
+  >>> print browser.contents
+  <html>...
+  ...Manfred the Second...
+  ...Really big and hairy...
+  ...
+
+  >>> browser.open("http://localhost/manfred/meet")
+  >>> browser.getControl(name="form.other").value = "Ellie"
+  >>> browser.getControl("Meet").click()
+  >>> print browser.contents
+  Manfred the Second meets Ellie
+"""
+import grok
+from zope import schema
+
+class Mammoth(grok.Model):
+    class fields:
+        name = schema.TextLine(title=u"Name")
+        size = schema.TextLine(title=u"Size")
+
+class Edit(grok.EditForm):
+    @grok.action("Apply")
+    def handle_apply(self, **data):
+        if self.applyData(self.context, **data):
+            self.status = 'Modified!'
+        else:
+            self.status = 'No changes!'
+
+    @grok.action("Hairy")
+    def handle_hairy(self, **data):
+        self.applyData(self.context, **data)
+        self.context.size += " and hairy"
+
+class Meet(grok.Form):
+    form_fields = grok.Fields(
+        other = schema.TextLine(title=u'Mammoth to meet with')
+        )
+
+    @grok.action('Meet')
+    def meet(self, other):
+        return self.context.name + ' meets ' + other


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/actions.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,70 @@
+"""
+We can use grok.AddForm to render an add form for objects:
+
+  >>> import grok
+  >>> from grok.ftests.form.addform import Zoo, Mammoth
+  >>> grok.grok('grok.ftests.form.addform')
+  >>> getRootFolder()["zoo"] = Zoo()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+
+  >>> browser.open("http://localhost/zoo/@@addmammoth")
+  >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
+  >>> browser.getControl(name="form.size").value = "Really big"
+  >>> browser.getControl("Add entry").click()
+  >>> print browser.contents
+  Hi, my name is Manfred the Mammoth, and I\'m "Really big"
+
+Instead of calling an object constructor with the form data, we can
+also use the ``applyData`` method to store the data on the object.
+
+  >>> browser.open("http://localhost/zoo/@@addmammothapplydata")
+  >>> browser.getControl(name="form.name").value = "Ellie the Mammoth"
+  >>> browser.getControl(name="form.size").value = "Really small"
+  >>> browser.getControl("Add entry").click()
+  >>> print browser.contents
+  Hi, my name is Ellie the Mammoth, and I\'m "Really small"
+
+"""
+import grok
+from zope import schema
+
+class Zoo(grok.Container):
+    pass
+
+class Mammoth(grok.Model):
+    class fields:
+        name = schema.TextLine(title=u"Name")
+        size = schema.TextLine(title=u"Size")
+
+    def __init__(self, name='', size=''):
+        self.name = name
+        self.size = size
+
+class Index(grok.View):
+    grok.context(Mammoth)
+    def render(self):
+        return 'Hi, my name is %s, and I\'m "%s"' % (self.context.name,
+                                                     self.context.size)
+
+class AddMammoth(grok.AddForm):
+    grok.context(Zoo)
+
+    form_fields = grok.AutoFields(Mammoth)
+
+    @grok.action('Add entry')
+    def add(self, **data):
+        # pass data into Mammoth constructor
+        self.context['manfred'] = manfred = Mammoth(**data)
+        self.redirect(self.url(manfred))
+
+class AddMammothApplyData(AddMammoth):
+
+    @grok.action('Add entry')
+    def add(self, **data):
+        # instantiate Mammoth and then use self.applyData()
+        self.context['ellie'] = ellie = Mammoth()
+        self.applyData(ellie, **data)
+        self.redirect(self.url(ellie))


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform_applydata.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform_applydata.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform_applydata.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,69 @@
+"""
+We can use AddFrom.applyData to save changes to a newly created
+object.  The object doesn't yet need to have the attributes that are
+going to be set on it.
+
+  >>> import grok
+  >>> from grok.ftests.form.addform_applydata import Zoo, Mammoth
+  >>> grok.grok('grok.ftests.form.addform_applydata')
+  >>> getRootFolder()["zoo"] = Zoo()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+
+AddForm.applyData() sends an IObjectModifiedEvent after having
+modified the object.  Its return value is True in a Boolean sense when
+the object has been modified:
+
+  >>> browser.open("http://localhost/zoo/@@addmammoth")
+  >>> browser.getControl(name="form.name").value = "Ellie the Mammoth"
+  >>> browser.getControl(name="form.size").value = "Really small"
+  >>> browser.getControl("Add entry").click()
+  An IObjectModifiedEvent was sent for a mammoth with the following changes:
+  IMammoth: name, size
+  >>> print browser.contents
+  There were changes according to applyData.
+
+  >>> browser.open("http://localhost/zoo/ellie")
+  >>> print browser.contents
+  Hi, my name is Ellie the Mammoth, and I\'m "Really small"
+
+"""
+import grok
+from zope import schema, interface
+
+class Zoo(grok.Container):
+    pass
+
+class IMammoth(interface.Interface):
+    name = schema.TextLine(title=u"Name")
+    size = schema.TextLine(title=u"Size")
+
+class Mammoth(grok.Model):
+    grok.implements(IMammoth)
+
+class Index(grok.View):
+    grok.context(Mammoth)
+    def render(self):
+        return 'Hi, my name is %s, and I\'m "%s"' % (self.context.name,
+                                                     self.context.size)
+
+class AddMammoth(grok.AddForm):
+    grok.context(Zoo)
+
+    form_fields = grok.AutoFields(IMammoth)
+
+    @grok.action('Add entry')
+    def add(self, **data):
+        self.context['ellie'] = ellie = Mammoth()
+        if self.applyData(ellie, **data):
+            return 'There were changes according to applyData.'
+        return 'There were no changes according to applyData.'
+
+ at grok.subscribe(Mammoth, grok.IObjectModifiedEvent)
+def notify_change_event(mammoth, event):
+    print ("An IObjectModifiedEvent was sent for a mammoth with the "
+           "following changes:")
+    for descr in event.descriptions:
+        print descr.interface.__name__ + ": " + ", ".join(descr.attributes)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform_applydata.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform_catalog.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform_catalog.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform_catalog.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,89 @@
+"""
+Thanks to Zope's event system, newly added objects are automatically
+catalogued, should a catalog be present.
+
+  >>> import grok
+  >>> from grok.ftests.form.addform_catalog import Zoo, Mammoth
+  >>> grok.grok('grok.ftests.form.addform_catalog')
+  >>> getRootFolder()["zoo"] = Zoo()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+
+Let's demonstrate that an object that has not been added to a
+container yet can still be modified using a form's applyData method.
+Event though this method triggers an IObjectModifiedEvent, the catalog
+won't be bothered by this.  It will start the indexation when the
+object has been *added* to a container, not before.
+
+  >>> browser.open("http://localhost/zoo/@@addmammoth")
+  >>> browser.getControl(name="form.name").value = "Ellie the Mammoth"
+  >>> browser.getControl(name="form.size").value = "Really small"
+  >>> browser.getControl("Add entry").click()
+
+  >>> browser.open("http://localhost/zoo/ellie")
+  >>> print browser.contents
+  Hi, my name is Ellie the Mammoth, and I\'m "Really small"
+
+Let's ensure the catalog has actually indexed the object with the
+right value:
+
+  >>> browser.open("http://localhost/zoo/search")
+  >>> print browser.contents
+  We found Ellie!
+
+"""
+import grok
+from zope import schema, interface, component
+from zope.app.intid import IntIds
+from zope.app.intid.interfaces import IIntIds
+from zope.app.catalog.catalog import Catalog
+from zope.app.catalog.interfaces import ICatalog
+from zope.app.catalog.field import FieldIndex
+
+def setup_catalog(catalog):
+    catalog['name'] = FieldIndex('name', IMammoth)
+
+class Zoo(grok.Site, grok.Container):
+    grok.local_utility(IntIds, provides=IIntIds)
+    grok.local_utility(Catalog, provides=ICatalog, setup=setup_catalog)
+
+class IMammoth(interface.Interface):
+    name = schema.TextLine(title=u"Name")
+    size = schema.TextLine(title=u"Size")
+
+class Mammoth(grok.Model):
+    grok.implements(IMammoth)
+
+class Index(grok.View):
+    grok.context(Mammoth)
+
+    def render(self):
+        return 'Hi, my name is %s, and I\'m "%s"' % (self.context.name,
+                                                     self.context.size)
+
+class Search(grok.View):
+    grok.context(Zoo)
+
+    def render(self):
+        catalog = component.getUtility(ICatalog)
+        query = ('Ellie the Mammoth', 'Ellie the Mammoth')
+        results = catalog.searchResults(name=query)
+        if len(list(results)) == 1:
+            return 'We found Ellie!'
+        return "Couldn't find Ellie."
+
+class AddMammoth(grok.AddForm):
+    grok.context(Zoo)
+
+    form_fields = grok.AutoFields(IMammoth)
+
+    @grok.action('Add entry')
+    def add(self, **data):
+        # First apply the form data, thus triggering an
+        # IObjectModifiedEvent.  This test case demonstrates that this
+        # isn't a problem.
+        ellie = Mammoth()
+        self.applyData(ellie, **data)
+        self.context['ellie'] = ellie


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/addform_catalog.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,92 @@
+"""
+A grok.EditForm uses applyData in update mode to save the form data on
+the object.  Update mode means that only those fields are changed on
+the object that need to be changed.
+
+  >>> import grok
+  >>> from grok.ftests.form.editform_applydata import Mammoth
+  >>> grok.grok('grok.ftests.form.editform_applydata')
+  >>> getRootFolder()["manfred"] = Mammoth('Manfred the Mammoth', 'Really big')
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+
+If we don't change any of the fields, there will no object modified
+event and applyData will report no changes:
+
+  >>> browser.open("http://localhost/manfred/@@edit")
+  >>> browser.getControl("Apply").click()
+  >>> 'No changes' in browser.contents
+  True
+
+If we change one field, only that attribute will be changed.  The
+object modified event also reflects that:
+
+  >>> browser.getControl(name="form.name").value = "Manfred the Big Mammoth"
+  >>> browser.getControl("Apply").click()
+  The 'name' property is being set.
+  An IObjectModifiedEvent was sent for a mammoth with the following changes:
+  name
+  >>> 'Updated' in browser.contents
+  True
+
+Let's change the other field:
+
+  >>> browser.getControl(name="form.size").value = "Enormously big"
+  >>> browser.getControl("Apply").click()
+  The 'size' property is being set.
+  An IObjectModifiedEvent was sent for a mammoth with the following changes:
+  size
+  >>> 'Updated' in browser.contents
+  True
+
+And finally let's change both fields:
+
+  >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
+  >>> browser.getControl(name="form.size").value = "Really big"
+  >>> browser.getControl("Apply").click()
+  The 'name' property is being set.
+  The 'size' property is being set.
+  An IObjectModifiedEvent was sent for a mammoth with the following changes:
+  name, size
+  >>> 'Updated' in browser.contents
+  True
+
+"""
+import grok
+from zope import schema
+
+class Mammoth(grok.Model):
+
+    def __init__(self, name='', size=''):
+        self._name = name
+        self._size = size
+
+    def getName(self):
+        return self._name
+    def setName(self, value):
+        print "The 'name' property is being set."
+        self._name = value
+    name = property(getName, setName)
+
+    def getSize(self):
+        return self._size
+    def setSize(self, value):
+        print "The 'size' property is being set."
+        self._size = value
+    size = property(getSize, setSize)
+
+class Edit(grok.EditForm):
+
+    form_fields = grok.Fields(
+        name = schema.TextLine(title=u"Name"),
+        size = schema.TextLine(title=u"Size")
+        )
+
+ at grok.subscribe(Mammoth, grok.IObjectModifiedEvent)
+def notify_change_event(mammoth, event):
+    print ("An IObjectModifiedEvent was sent for a mammoth with the "
+           "following changes:")
+    for descr in event.descriptions:
+        print ", ".join(descr.attributes)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata_classfields.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata_classfields.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata_classfields.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,75 @@
+"""
+A grok.EditForm uses applyData in update mode to save the form data on
+the object.  Update mode means that only those fields are changed on
+the object that need to be changed.
+
+This is essentially the same narrative as 'editform_applydata'. Here
+we test the whole procedure on fields defined on the model class:
+
+  >>> import grok
+  >>> from grok.ftests.form.editform_applydata_classfields import Mammoth
+  >>> grok.grok('grok.ftests.form.editform_applydata_classfields')
+  >>> getRootFolder()["manfred"] = mammoth = Mammoth()
+  >>> mammoth.name = 'Manfred the Mammoth'
+  >>> mammoth.size = 'Really big'
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+
+If we don't change any of the fields, there will no object modified
+event and applyData will report no changes:
+
+  >>> browser.open("http://localhost/manfred/@@edit")
+  >>> browser.getControl("Apply").click()
+  >>> 'No changes' in browser.contents
+  True
+
+If we change one field, only that attribute will be changed.  The
+object modified event also reflects that:
+
+  >>> browser.getControl(name="form.name").value = "Manfred the Big Mammoth"
+  >>> browser.getControl("Apply").click()
+  An IObjectModifiedEvent was sent for a mammoth with the following changes:
+  name
+  >>> 'Updated' in browser.contents
+  True
+
+Let's change the other field:
+
+  >>> browser.getControl(name="form.size").value = "Enormously big"
+  >>> browser.getControl("Apply").click()
+  An IObjectModifiedEvent was sent for a mammoth with the following changes:
+  size
+  >>> 'Updated' in browser.contents
+  True
+
+And finally let's change both fields:
+
+  >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
+  >>> browser.getControl(name="form.size").value = "Really big"
+  >>> browser.getControl("Apply").click()
+  An IObjectModifiedEvent was sent for a mammoth with the following changes:
+  name, size
+  >>> 'Updated' in browser.contents
+  True
+
+"""
+import grok
+from zope import schema
+
+
+class Mammoth(grok.Model):
+    class fields:
+        name = schema.TextLine(title=u"Name")
+        size = schema.TextLine(title=u"Size")
+
+class Edit(grok.EditForm):
+    pass
+
+ at grok.subscribe(Mammoth, grok.IObjectModifiedEvent)
+def notify_change_event(mammoth, event):
+    print ("An IObjectModifiedEvent was sent for a mammoth with the "
+           "following changes:")
+    for descr in event.descriptions:
+        print ", ".join(descr.attributes)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata_classfields.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata_schema.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata_schema.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata_schema.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,96 @@
+"""
+A grok.EditForm uses applyData in update mode to save the form data on
+the object.  Update mode means that only those fields are changed on
+the object that need to be changed.
+
+This is essentially the same narrative as 'editform_applydata'. Here
+we test the whole procedure on fields from schemas:
+
+  >>> import grok
+  >>> from grok.ftests.form.editform_applydata_schema import Mammoth
+  >>> grok.grok('grok.ftests.form.editform_applydata_schema')
+  >>> getRootFolder()["manfred"] = Mammoth('Manfred the Mammoth', 'Really big')
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+
+If we don't change any of the fields, there will no object modified
+event and applyData will report no changes:
+
+  >>> browser.open("http://localhost/manfred/@@edit")
+  >>> browser.getControl("Apply").click()
+  >>> 'No changes' in browser.contents
+  True
+
+If we change one field, only that attribute will be changed.  The
+object modified event also reflects that:
+
+  >>> browser.getControl(name="form.name").value = "Manfred the Big Mammoth"
+  >>> browser.getControl("Apply").click()
+  The 'name' property is being set.
+  An IObjectModifiedEvent was sent for a mammoth with the following changes:
+  IMammoth: name
+  >>> 'Updated' in browser.contents
+  True
+
+Let's change the other field:
+
+  >>> browser.getControl(name="form.size").value = "Enormously big"
+  >>> browser.getControl("Apply").click()
+  The 'size' property is being set.
+  An IObjectModifiedEvent was sent for a mammoth with the following changes:
+  IMammoth: size
+  >>> 'Updated' in browser.contents
+  True
+
+And finally let's change both fields:
+
+  >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
+  >>> browser.getControl(name="form.size").value = "Really big"
+  >>> browser.getControl("Apply").click()
+  The 'name' property is being set.
+  The 'size' property is being set.
+  An IObjectModifiedEvent was sent for a mammoth with the following changes:
+  IMammoth: name, size
+  >>> 'Updated' in browser.contents
+  True
+
+"""
+import grok
+from zope import schema, interface
+
+class IMammoth(interface.Interface):
+    name = schema.TextLine(title=u"Name")
+    size = schema.TextLine(title=u"Size")
+
+class Mammoth(grok.Model):
+    grok.implements(IMammoth)
+
+    def __init__(self, name='', size=''):
+        self._name = name
+        self._size = size
+
+    def getName(self):
+        return self._name
+    def setName(self, value):
+        print "The 'name' property is being set."
+        self._name = value
+    name = property(getName, setName)
+
+    def getSize(self):
+        return self._size
+    def setSize(self, value):
+        print "The 'size' property is being set."
+        self._size = value
+    size = property(getSize, setSize)
+
+class Edit(grok.EditForm):
+    form_fields = grok.AutoFields(IMammoth)
+
+ at grok.subscribe(Mammoth, grok.IObjectModifiedEvent)
+def notify_change_event(mammoth, event):
+    print ("An IObjectModifiedEvent was sent for a mammoth with the "
+           "following changes:")
+    for descr in event.descriptions:
+        print descr.interface.__name__ + ": " + ", ".join(descr.attributes)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/editform_applydata_schema.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/form.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/form.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/form.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,45 @@
+"""
+A grok.EditForm is a special grok.View that renders an edit form.
+
+  >>> import grok
+  >>> from grok.ftests.form.form import Mammoth
+  >>> grok.grok('grok.ftests.form.form')
+  >>> getRootFolder()["manfred"] = Mammoth()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/manfred/@@edit")
+  >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
+  >>> browser.getControl(name="form.size").value = "Really big"
+  >>> browser.getControl("Apply").click()
+  >>> print browser.contents
+  <html>...
+  ...Manfred the Mammoth...
+  ...Really big...
+  ...
+
+grok.DisplayForm renders a display form:
+
+  >>> browser.open("http://localhost/manfred/@@display")
+  >>> print browser.contents
+  <html>...
+  ...Manfred the Mammoth...
+  ...Really big...
+  ...
+
+"""
+import grok
+from zope import schema
+
+class Mammoth(grok.Model):
+    class fields:
+        name = schema.TextLine(title=u"Name")
+        size = schema.TextLine(title=u"Size")
+
+class Edit(grok.EditForm):
+    pass
+
+class Display(grok.DisplayForm):
+    pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/form.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/templateform.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/templateform.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/templateform.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,78 @@
+"""
+If a form does not have a template, a simple default template is
+associated with them. Otherwise, the supplied template is used.
+
+  >>> import grok
+  >>> from grok.ftests.form.templateform import Mammoth
+  >>> grok.grok('grok.ftests.form.templateform')
+
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+  
+Default edit template:
+
+  >>> view = component.getMultiAdapter((Mammoth(), request), name='edit')
+  >>> print view()
+  <html>...
+  
+Custom edit template:
+
+  >>> view = component.getMultiAdapter((Mammoth(), request), name='edit2')
+  >>> print view()
+  <p>Test edit</p>
+
+Custom edit template with an explicit template
+
+  >>> view = component.getMultiAdapter((Mammoth(), request), name='edit3')
+  >>> print view()
+  <p>Test edit</p>
+
+Default display template:
+
+  >>> view = component.getMultiAdapter((Mammoth(), request), name='display')
+  >>> print view()
+  <html>...
+  
+Custom display template:
+
+  >>> view = component.getMultiAdapter((Mammoth(), request), name='display2')
+  >>> print view()
+  <p>Test display</p>
+
+Custom display template with an explicit template:
+
+  >>> view = component.getMultiAdapter((Mammoth(), request), name='display3')
+  >>> print view()
+  <p>Test display</p>
+
+"""
+import grok
+from zope import schema
+
+class Mammoth(grok.Model):
+    class fields:
+        name = schema.TextLine(title=u"Name")
+        size = schema.TextLine(title=u"Size", default=u"Quite normal")
+
+class Edit(grok.EditForm):
+    pass
+
+class Edit2(grok.EditForm):
+    pass
+
+edit2 = grok.PageTemplate('<p>Test edit</p>')
+
+class Edit3(grok.EditForm):
+    grok.template('edit2')
+
+class Display(grok.DisplayForm):
+    pass
+
+class Display2(grok.DisplayForm):
+    pass
+
+display2 = grok.PageTemplate('<p>Test display</p>')
+
+class Display3(grok.DisplayForm):
+    grok.template('display2')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/templateform.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/update.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/update.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/update.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,90 @@
+"""
+Forms can implement an update() method that will be called before any
+form processing has happened:
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.form.update')
+  >>> from grok.ftests.form.update import Mammoth
+  >>> getRootFolder()["manfred"] = Mammoth()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/manfred/edit")
+  >>> browser.getControl(name="form.name").value = "Ellie"
+  >>> browser.getControl("Apply").click()
+
+  >>> browser.open("http://localhost/manfred")
+  >>> print browser.contents
+  Ellie, the Mammoth reports: The form's update() was called and my name was Manfred.
+
+A form's update() method can issue a redirect.  In that case, the form
+won't proceed to do any form processing nor rendering:
+
+  >>> browser.open("http://localhost/manfred/editredirect")
+  >>> browser.getControl(name="form.name").value = "Mallie"
+  >>> browser.getControl("Apply").click()
+  >>> print browser.url
+  http://localhost/manfred/index
+
+Because of the redirect, no changes happened to the edited object:
+
+  >>> print browser.contents
+  Ellie, the Mammoth reports: The form's update() was called and my name was Manfred.
+
+A form's update() method may also take arbitrary parameters that will
+be filled with values from the request (such as form values):
+
+  >>> browser.open("http://localhost/manfred/editupdatewitharguments")
+  >>> browser.getControl(name="report").value = "Request argument dispatch to update() works."
+  >>> browser.getControl(name="form.name").value = "Mallie"
+  >>> browser.getControl("Apply").click()
+
+  >>> browser.open("http://localhost/manfred")
+  >>> print browser.contents
+  Mallie, the Mammoth reports: Request argument dispatch to update() works.
+
+"""
+import grok
+from zope import schema
+
+class Mammoth(grok.Model):
+    class fields:
+        name = schema.TextLine(title=u"Name", default=u'Manfred')
+
+class Index(grok.View):
+
+    def render(self):
+        return "%s, the Mammoth reports: %s" % (self.context.name,
+                                                self.context.report)
+
+class Edit(grok.EditForm):
+
+    def update(self):
+        self.context.report = ("The form's update() was called and my name "
+                               "was %s." % self.context.name)
+
+class EditRedirect(grok.EditForm):
+
+    def update(self):
+        # redirect upon form submit so that no changes are ever saved
+        if 'form.name' in self.request:
+            self.redirect(self.url('index'))
+
+class EditUpdateWithArguments(grok.EditForm):
+
+    def update(self, report=None):
+        if report is not None:
+            self.context.report = report
+
+editupdatewitharguments = grok.PageTemplate("""
+<html>
+<body>
+<form action="" tal:attributes="action request/URL">
+  <input type="text" name="report" />
+  <div tal:repeat="widget view/widgets" tal:content="structure widget" />
+  <div tal:repeat="action view/actions" tal:content="structure action/render" />
+</form>
+</body>
+</html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/form/update.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/grant.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/grant.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/grant.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,31 @@
+# -*- coding: latin-1 -*-
+"""
+We can define a few permissions with grok.define_permission:
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.security.grant')
+
+and then take a look at them in Zope 3's grant view:
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+
+  >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+  >>> browser.open("http://localhost/@@grant.html")
+
+  >>> browser.getControl(name='field.principal.MA__.searchstring').value = 'manager'
+  >>> browser.getControl('Search').click()
+  >>> browser.getControl('Apply').click()
+  >>> 'grok.ascii-permission' in browser.contents
+  True
+
+"""
+import grok
+grok.define_permission('grok.ascii-permission')
+
+# TODO Technically, it's absolutely possible to give permissions
+# non-ASCII names. However the way Zope 3's grant view uses widgets to
+# display form controls for each permission is not unicode-safe.
+
+#grok.define_permission(u'grok.ünicöde-permission')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/grant.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/handle_exception.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/handle_exception.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/handle_exception.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,45 @@
+"""
+
+The handleException() method has a special case that might introduce a proxy
+and cause the grok security to fail, we have a simple test here that assures
+that we don't hit this:
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.security.handle_exception')
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.open("http://localhost/@@cave")
+  Traceback (most recent call last):
+  HTTPError: HTTP Error 500: Internal Server Error
+  >>> browser.contents
+  "It's gone!"
+
+"""
+
+import zope.interface
+
+import grok
+
+
+class CaveWasRobbedError(Exception):
+    pass
+
+
+class Cave(grok.View):
+
+    grok.context(zope.interface.Interface)
+
+    fire = "It's gone!"
+
+    def render(self):
+        raise CaveWasRobbedError("EVERYTHING GONE! GROK ANGRY!")
+
+
+class CaveErrorView(grok.View):
+
+    grok.context(CaveWasRobbedError)
+    grok.name("index.html")
+
+    def render(self):
+        self.request.response.setStatus(500)
+        return self.context.__parent__.fire


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/handle_exception.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/json.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/json.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/json.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,44 @@
+"""
+Let's test whether require decorators work for json methods.
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.security.json')
+  
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+
+We can access the public method just fine::
+
+  >>> browser.open('http://localhost/stomp')
+  >>> print browser.contents
+  {"Manfred stomped.": ""}
+
+We cannot access the protected method however::
+
+  >>> browser.open('http://localhost/dance')
+  Traceback (most recent call last):
+    ...
+  Unauthorized: (<grok.meta.MammothJSON object at ...>, '__call__', 'zope.ManageContent')
+
+Let's log in as the manager now. We should be able to access the method now::
+
+  >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+  >>> browser.open('http://localhost/dance')
+  >>> print browser.contents
+  {"Manfred doesn't like to dance.": ""}
+  
+"""
+
+import grok
+import zope.interface
+
+class MammothJSON(grok.JSON):
+    grok.context(zope.interface.Interface)
+
+    def stomp(self):
+        return {'Manfred stomped.': ''}
+
+    @grok.require('zope.ManageContent')
+    def dance(self):
+        return {'Manfred doesn\'t like to dance.': ''}


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/json.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/require.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/require.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/require.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,52 @@
+"""
+  >>> import grok
+  >>> grok.grok('grok.ftests.security.require')
+
+Viewing a protected view with insufficient privileges will yield
+Unauthorized:
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.open("http://localhost/@@cavepainting")
+  Traceback (most recent call last):
+  HTTPError: HTTP Error 401: Unauthorized
+
+When we log in (e.g. as a manager), we can access the view just fine:
+
+  >>> from zope.app.securitypolicy.rolepermission import rolePermissionManager
+  >>> rolePermissionManager.grantPermissionToRole('grok.ViewPainting',
+  ...                                             'zope.Manager')
+  >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/@@cavepainting")
+  >>> print browser.contents
+  What a beautiful painting.
+
+A view protected with 'zope.Public' is always accessible:
+
+  >>> browser = Browser()
+  >>> browser.open("http://localhost/@@publicnudity")
+  >>> print browser.contents
+  Everybody can see this.
+"""
+
+import grok
+import zope.interface
+
+grok.define_permission('grok.ViewPainting')
+
+class CavePainting(grok.View):
+
+    grok.context(zope.interface.Interface)
+    grok.require('grok.ViewPainting')
+
+    def render(self):
+        return 'What a beautiful painting.'
+
+class PublicNudity(grok.View):
+
+    grok.context(zope.interface.Interface)
+    grok.require('zope.Public')
+
+    def render(self):
+        return 'Everybody can see this.'


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/require.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/xmlrpc.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/xmlrpc.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/xmlrpc.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,67 @@
+"""
+  >>> import grok
+  >>> grok.grok('grok.ftests.security.xmlrpc')
+
+  >>> from grok.ftests.xmlrpc_helper import ServerProxy
+
+  >>> server = ServerProxy("http://localhost/")
+  >>> mgr_server = ServerProxy("http://mgr:mgrpw@localhost/")
+
+We can access a public method just fine, but a protected method will
+raise Unauthorized:
+
+  >>> print server.stomp()
+  Manfred stomped.
+
+  >>> print server.dance()
+  Traceback (most recent call last):
+  ProtocolError: <ProtocolError for localhost/: 401 401 Unauthorized>
+
+With manager privileges, the protected method is accessible, however:
+
+  >>> print mgr_server.dance()  
+  Manfred doesn't like to dance.
+
+The same applies when a default permission is defined for all XML-RPC
+methods in a class:
+
+  >>> print server.hunt()
+  Traceback (most recent call last):
+  ProtocolError: <ProtocolError for localhost/: 401 401 Unauthorized>
+
+  >>> print mgr_server.hunt()
+  ME GROK LIKE MAMMOTH!
+
+  >>> print server.eat()
+  MMM, MANFRED TASTE GOOD!
+
+  >>> print server.rest()
+  ME GROK TIRED!
+"""
+import grok
+import zope.interface
+
+class MammothRPC(grok.XMLRPC):
+    grok.context(zope.interface.Interface)
+
+    def stomp(self):
+        return 'Manfred stomped.'
+
+    @grok.require('zope.ManageContent')
+    def dance(self):
+        return 'Manfred doesn\'t like to dance.'
+
+class CavemanRPC(grok.XMLRPC):
+    grok.context(zope.interface.Interface)
+    grok.require('zope.ManageContent')
+
+    def hunt(self):
+        return 'ME GROK LIKE MAMMOTH!'
+
+    @grok.require('zope.View')
+    def eat(self):
+        return 'MMM, MANFRED TASTE GOOD!'
+
+    @grok.require('zope.Public')
+    def rest(self):
+        return 'ME GROK TIRED!'


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/security/xmlrpc.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,67 @@
+"""
+If there is a static/ directory inside of a grokked package, its
+contents will be available as static resources under a URL:
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.static.simple_fixture')
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open('http://localhost/@@/grok.ftests.static.simple_fixture/'
+  ...              'file.txt')
+  >>> print browser.contents
+  some text
+
+We use a special name 'static' in page templates to allow easy linking
+to resources:
+
+  >>> root = getRootFolder()
+  >>> from grok.ftests.static.simple_fixture.ellie import Mammoth
+  >>> root[u'ellie'] = Mammoth()
+  >>> browser.open('http://localhost/ellie')
+  >>> print browser.contents
+  <html>
+  <body>
+  <a href="http://localhost/@@/grok.ftests.static.simple_fixture/file.txt">Some text in a file</a>
+  </body>
+  </html>
+
+Static also means that page templates will not be interpreted:
+
+  >>> browser.open('http://localhost/@@/grok.ftests.static.simple_fixture/static.pt')
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1 tal:content="string:will not be interpreted"/>
+  </body>
+  </html>
+
+We also support subdirectories for resources:
+
+  >>> browser.open('http://localhost/@@/grok.ftests.static.simple_fixture/subdir/otherfile.txt')
+  >>> print browser.contents
+  This is yet another file.
+
+Sanity check custom layers
+
+  >>> browser.open('http://localhost/ellie/@@cavedrawings')
+  >>> print browser.contents
+  stick figures
+
+  >>> browser.open('http://localhost/++skin++mammothskin/ellie/@@tarpit')
+  >>> print browser.contents
+  inky darkness all around
+
+
+grok.ILayer now inherits IDefaultBrowserLayer
+
+  >>> browser.open('http://localhost/++skin++mammothskin/@@/grok.ftests.static.simple_fixture/subdir/otherfile.txt')
+  >>> print browser.contents
+  This is yet another file.
+
+
+  >>> browser.open('http://localhost/++skin++Rotterdam/@@/grok.ftests.static.simple_fixture/subdir/otherfile.txt')
+  >>> print browser.contents
+  This is yet another file.
+  
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/ellie.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/ellie.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/ellie.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,35 @@
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class Index(grok.View):
+    grok.context(Mammoth)
+
+index = grok.PageTemplate("""\
+<html>
+<body>
+<a tal:attributes="href static/file.txt">Some text in a file</a>
+</body>
+</html>""")
+
+class MammothLayer(grok.ILayer):
+    pass
+
+class MammothSkin(grok.Skin):
+    grok.layer(MammothLayer)
+
+
+class CaveDrawings(grok.View):
+    grok.context(Mammoth)
+
+    def render(self):
+        return "stick figures"
+
+class TarPit(grok.View):
+    grok.context(Mammoth)
+    grok.layer(MammothLayer)
+
+    def render(self):
+        return "inky darkness all around"
+    


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/ellie.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/file.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/file.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/file.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+some text


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/file.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/static.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/static.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/static.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<h1 tal:content="string:will not be interpreted"/>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/subdir/otherfile.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/subdir/otherfile.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/subdir/otherfile.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+This is yet another file.


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/static/simple_fixture/static/subdir/otherfile.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/test_grok_functional.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/test_grok_functional.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/test_grok_functional.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,66 @@
+import unittest
+from pkg_resources import resource_listdir
+from zope.testing import doctest
+from zope.app.testing.functional import (HTTPCaller, getRootFolder,
+                                         FunctionalTestSetup, sync, Functional)
+
+# XXX bastardized from zope.app.testing.functional.FunctionalDocFileSuite :-(
+def FunctionalDocTestSuite(*paths, **kw):
+    globs = kw.setdefault('globs', {})
+    globs['http'] = HTTPCaller()
+    globs['getRootFolder'] = getRootFolder
+    globs['sync'] = sync
+
+    #kw['package'] = doctest._normalize_module(kw.get('package'))
+
+    kwsetUp = kw.get('setUp')
+    def setUp(test):
+        FunctionalTestSetup().setUp()
+
+        if kwsetUp is not None:
+            kwsetUp(test)
+    kw['setUp'] = setUp
+
+    kwtearDown = kw.get('tearDown')
+    def tearDown(test):
+        if kwtearDown is not None:
+            kwtearDown(test)
+        FunctionalTestSetup().tearDown()
+    kw['tearDown'] = tearDown
+
+    if 'optionflags' not in kw:
+        old = doctest.set_unittest_reportflags(0)
+        doctest.set_unittest_reportflags(old)
+        kw['optionflags'] = (old
+                             | doctest.ELLIPSIS
+                             | doctest.REPORT_NDIFF
+                             | doctest.NORMALIZE_WHITESPACE)
+
+    suite = doctest.DocTestSuite(*paths, **kw)
+    suite.layer = Functional
+    return suite
+
+def suiteFromPackage(name):
+    files = resource_listdir(__name__, name)
+    suite = unittest.TestSuite()
+    for filename in files:
+        if not filename.endswith('.py'):
+            continue
+        if filename == '__init__.py':
+            continue
+
+        dottedname = 'grok.ftests.%s.%s' % (name, filename[:-3])
+        test = FunctionalDocTestSuite(dottedname)
+
+        suite.addTest(test)
+    return suite
+
+def test_suite():
+    suite = unittest.TestSuite()
+    for name in ['view', 'static', 'xmlrpc', 'traversal', 'form', 'url',
+                 'security', 'utility', 'catalog', 'admin']:
+        suite.addTest(suiteFromPackage(name))
+    return suite
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/test_grok_functional.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/containertraverse.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/containertraverse.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/containertraverse.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,105 @@
+"""
+Containers can determine how they want to be traversed by
+implementing a 'traverse' method, but the behavior falls back to
+basic container traversal if the 'traverse' method returns None:
+
+  >>> import grok
+  >>> from grok.ftests.traversal.containertraverse import Herd, Mammoth
+  >>> grok.grok('grok.ftests.traversal.containertraverse')
+  >>> getRootFolder()["herd"] = herd = Herd()
+  >>> herd['manfred'] = Mammoth('Manfred')
+  >>> herd['ellie'] = Mammoth('Ellie')
+
+Let's first try to look up the special traversed item:
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/herd/special")
+  >>> print browser.contents
+  special view
+  >>> browser.open("http://localhost/herd/special/index")
+  >>> print browser.contents
+  special view
+
+Even if we have a container item called 'special', we should still
+get our special object:
+
+  >>> herd['special'] = Mammoth('Special invisible mammoth')
+  >>> browser.open("http://localhost/herd/special")
+  >>> print browser.contents
+  special view
+  >>> browser.open("http://localhost/herd/special/index")
+  >>> print browser.contents
+  special view
+  
+The fall-back behavior should work for items that aren't traversed:
+
+  >>> browser.open("http://localhost/herd/manfred")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, Manfred!</h1>
+  </body>
+  </html>
+
+  >>> browser.open("http://localhost/herd/ellie")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, Ellie!</h1>
+  </body>
+  </html>
+
+Also try (an empty and therefore False in a Boolean sense) container
+as a subitem of a container:
+
+  >>> herd['subherd'] = Herd()
+  >>> browser.open("http://localhost/herd/subherd")
+  >>> print browser.contents
+  A herd
+
+"""
+import grok
+
+class Herd(grok.Container):
+
+    def traverse(self, name):
+        if name == 'special':
+            return Special()
+        return None
+    
+class HerdIndex(grok.View):
+    grok.context(Herd)
+    grok.name('index')
+
+    def render(self):
+        return 'A herd'
+
+class Mammoth(grok.Model):
+
+    def __init__(self, name):
+        self.name = name
+
+class Special(grok.Model):
+    pass
+
+class SpecialIndex(grok.View):
+    grok.context(Special)
+    grok.name('index')
+    
+    def render(self):
+        return "special view"
+
+grok.context(Mammoth)
+
+class Index(grok.View):
+    pass
+
+index = grok.PageTemplate("""\
+<html>
+<body>
+<h1>Hello, <span tal:replace="context/name/title" />!</h1>
+</body>
+</html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/containertraverse.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/containertraverser.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/containertraverser.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/containertraverser.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,100 @@
+"""
+Containers can also have an explicit traverser associated with them.
+The behavior falls back to basic container traversal if the 'traverse'
+method returns None:
+
+  >>> import grok
+  >>> from grok.ftests.traversal.containertraverser import Herd, Mammoth
+  >>> grok.grok('grok.ftests.traversal.containertraverser')
+  >>> getRootFolder()["herd"] = herd = Herd()
+  >>> herd['manfred'] = Mammoth('Manfred')
+  >>> herd['ellie'] = Mammoth('Ellie')
+
+Let's first try to look up the special traversed item:
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/herd/special")
+  >>> print browser.contents
+  special view
+  >>> browser.open("http://localhost/herd/special/index")
+  >>> print browser.contents
+  special view
+
+Even if we have a container item called 'special', we should still
+get our special object:
+
+  >>> herd['special'] = Mammoth('Special invisible mammoth')
+  >>> browser.open("http://localhost/herd/special")
+  >>> print browser.contents
+  special view
+  >>> browser.open("http://localhost/herd/special/index")
+  >>> print browser.contents
+  special view
+  
+The fall-back behavior should work for items that aren't traversed:
+
+  >>> browser.open("http://localhost/herd/manfred")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, Manfred!</h1>
+  </body>
+  </html>
+
+  >>> browser.open("http://localhost/herd/ellie")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, Ellie!</h1>
+  </body>
+  </html>
+
+Also try traversing (an empty and therefore False in a Boolean sense) container
+as a subitem of a container:
+
+  >>> herd['subherd'] = Herd()
+  >>> browser.open("http://localhost/herd/subherd/special")
+  >>> print browser.contents
+  special view
+
+"""
+import grok
+
+class Herd(grok.Container):
+    pass
+
+class Traverser(grok.Traverser):
+    grok.context(Herd)
+    def traverse(self, name):
+        if name == 'special':
+            return Special()
+        return None
+
+class Mammoth(grok.Model):
+    def __init__(self, name):
+        self.name = name
+
+class Special(grok.Model):
+    pass
+
+class SpecialIndex(grok.View):
+    grok.context(Special)
+    grok.name('index')
+    
+    def render(self):
+        return "special view"
+
+grok.context(Mammoth)
+
+class Index(grok.View):
+    pass
+
+index = grok.PageTemplate("""\
+<html>
+<body>
+<h1>Hello, <span tal:replace="context/name/title" />!</h1>
+</body>
+</html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/containertraverser.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/items_before_views.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/items_before_views.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/items_before_views.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,67 @@
+"""
+Containers can have an explicit traverser associated with them.  The
+behaviour falls back to basic container traversal if the 'traverse'
+method returns None. Normal behaviour also means that the standard
+Zope 3 paradigm"items before views" is supported in the fallback.
+
+  >>> import grok
+  >>> from grok.ftests.traversal.items_before_views import Herd, Mammoth
+  >>> grok.grok('grok.ftests.traversal.items_before_views')
+  >>> getRootFolder()["herd"] = herd = Herd()
+  >>> herd['manfred'] = Mammoth('Manfred')
+  >>> herd['ellie'] = Mammoth('Ellie')
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+
+When we look up 'manfred', we'll get the Mammoth object as expected:
+
+  >>> browser.open("http://localhost/herd/manfred")
+  >>> print browser.contents
+  Hello Manfred
+
+When we look up 'ellie', we also get a Mammoth object and not the
+Ellie view:
+
+  >>> browser.open("http://localhost/herd/ellie")
+  >>> print browser.contents
+  Hello Ellie
+
+We can, of course, get to the Ellie view explicitly:
+
+  >>> browser.open("http://localhost/herd/@@ellie")
+  >>> print browser.contents
+  Hi, it's me, the Ellie view!
+
+"""
+import grok
+
+class Herd(grok.Container):
+    pass
+
+class Traverser(grok.Traverser):
+    grok.context(Herd)
+
+    def traverse(self, name):
+        # we don't really need to do anything here as we want to test
+        # the fallback behaviour
+        pass
+
+class Ellie(grok.View):
+    grok.context(Herd)
+    grok.name('ellie')
+
+    def render(self):
+        return "Hi, it's me, the Ellie view!"
+
+class Mammoth(grok.Model):
+    def __init__(self, name):
+        self.name = name
+
+class MammothIndex(grok.View):
+    grok.context(Mammoth)
+    grok.name('index')
+
+    def render(self):
+        return "Hello " + self.context.name.title()


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/items_before_views.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/modeltraverse.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/modeltraverse.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/modeltraverse.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,56 @@
+"""
+Models can determine how they want to be traversed by
+implementing a 'traverse' method:
+
+  >>> import grok
+  >>> from grok.ftests.traversal.modeltraverse import Herd
+  >>> grok.grok('grok.ftests.traversal.modeltraverse')
+  >>> getRootFolder()["herd"] = Herd()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/herd/manfred")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, Manfred!</h1>
+  </body>
+  </html>
+
+  >>> browser.open("http://localhost/herd/ellie")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, Ellie!</h1>
+  </body>
+  </html>
+
+"""
+import grok
+
+class Herd(grok.Model):
+
+    def getMammoth(self, name):
+        return Mammoth(name)
+
+    def traverse(self, name):
+        return self.getMammoth(name)
+    
+class Mammoth(grok.Model):
+
+    def __init__(self, name):
+        self.name = name
+
+grok.context(Mammoth)
+
+class Index(grok.View):
+    pass
+
+index = grok.PageTemplate("""\
+<html>
+<body>
+<h1>Hello, <span tal:replace="context/name/title" />!</h1>
+</body>
+</html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/modeltraverse.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/traverser.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/traverser.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/traverser.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,57 @@
+"""
+Apart from using the ``traverse`` method on a model, you can
+also create a separate traverser component:
+
+  >>> import grok
+  >>> from grok.ftests.traversal.traverser import Herd
+  >>> grok.grok('grok.ftests.traversal.traverser')
+  >>> getRootFolder()["herd"] = Herd()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/herd/manfred")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, Manfred!</h1>
+  </body>
+  </html>
+
+  >>> browser.open("http://localhost/herd/ellie")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, Ellie!</h1>
+  </body>
+  </html>
+
+"""
+import grok
+
+class Herd(grok.Model):
+    pass
+
+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
+
+grok.context(Mammoth)
+
+class Index(grok.View):
+    pass
+
+index = grok.PageTemplate("""\
+<html>
+<body>
+<h1>Hello, <span tal:replace="context/name/title" />!</h1>
+</body>
+</html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/traversal/traverser.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/application.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/application.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/application.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,69 @@
+"""
+Views have an application_url() method to easily retrieve the url of the
+application::
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.url.application')
+
+  >>> from grok.ftests.url.application import Cave, CaveMan
+  >>> getRootFolder()['cave'] = cave = Cave()
+  >>> cave['caveman'] = CaveMan()
+
+Asking for the application_url on the cave returns the URL to the cave::
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open('http://localhost/cave')
+  >>> browser.contents
+  'http://localhost/cave'
+  
+Asking for the application_url on the caveman returns the URL to the cave as
+well::
+
+  >>> browser.open('http://localhost/cave/caveman')
+  >>> browser.contents
+  'http://localhost/cave'
+
+You can pass a name to specify a particular view or sub object to add
+to the URL::
+
+  >>> browser.open('http://localhost/cave/caveman/second')
+  >>> browser.contents
+  'http://localhost/cave/second'
+
+application_url also works with empty containers::
+
+  >>> from grok.ftests.url.application import Corridors
+  >>> cave['corridors'] = Corridors()
+  >>> browser.open('http://localhost/cave/corridors')
+  >>> browser.contents
+  'http://localhost/cave'
+  
+"""
+import zope.interface
+
+import grok
+
+
+class Index(grok.View):
+    grok.context(zope.interface.Interface)
+
+    def render(self):
+        return self.application_url()
+
+class Second(grok.View):
+    grok.context(zope.interface.Interface)
+
+    def render(self):
+        return self.application_url('second')
+    
+class Cave(grok.Application, grok.Container):
+    pass
+
+
+class CaveMan(grok.Model):
+    pass
+
+class Corridors(grok.Container):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/application.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/redirect.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/redirect.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/redirect.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,34 @@
+"""
+Views have a redirect() method to easily create redirects:
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.url.redirect')
+
+  >>> from grok.ftests.url.redirect import Mammoth
+  >>> getRootFolder()['manfred'] = manfred = Mammoth()
+
+Since the index view redirects to mammoth, we expect to see the URL
+point to mammoth:
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open('http://localhost/manfred')
+  >>> browser.url
+  'http://localhost/manfred/another'
+  
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class Index(grok.View):
+    def render(self):
+        self.redirect(self.url('another'))
+
+class Another(grok.View):
+    def render(self):
+        return "Another view"
+    
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/redirect.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/url.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/url.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/url.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,127 @@
+# -*- coding: UTF-8 -*-
+"""
+Views have a method that can be used to construct URLs:
+
+  >>> import grok
+  >>> grok.grok('grok.ftests.url.url')
+
+  >>> from grok.ftests.url.url import Herd, Mammoth
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  >>> manfred = Mammoth()
+  >>> herd['manfred'] = manfred
+
+The views in this test implement self.url():
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/herd/manfred/index")
+  >>> print browser.contents
+  http://localhost/herd/manfred/index
+  >>> browser.open("http://localhost/herd/manfred/another")
+  >>> print browser.contents
+  http://localhost/herd/manfred/another
+  >>> browser.open("http://localhost/herd/manfred/yetanother")
+  >>> print browser.contents
+  http://localhost/herd/manfred/yetanother
+  
+We get the views manually so we can do a greater variety of url() calls:
+
+  >>> from zope import component
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> index_view = component.getMultiAdapter((manfred, request), name='index')
+  >>> index_view.url()
+  'http://127.0.0.1/herd/manfred/index'
+  >>> another_view = component.getMultiAdapter((manfred, request),
+  ...                                              name='another')
+  >>> another_view.url()
+  'http://127.0.0.1/herd/manfred/another'
+  >>> yet_another_view = component.getMultiAdapter((manfred, request),
+  ...                                              name='yetanother')
+  >>> yet_another_view.url()
+  'http://127.0.0.1/herd/manfred/yetanother'
+
+Now let's get a URL for a specific object:
+
+  >>> index_view.url(manfred)
+  'http://127.0.0.1/herd/manfred'
+
+This works with any other view too (as they share the same request):
+
+  >>> another_view.url(manfred)
+  'http://127.0.0.1/herd/manfred'
+
+This shows that the default argument is the view itself:
+
+  >>> another_view.url(another_view)
+  'http://127.0.0.1/herd/manfred/another'
+
+We can get the URL for any object in content-space:
+
+  >>> another_view.url(herd)
+  'http://127.0.0.1/herd'
+
+We can also pass a name along with this, to generate a URL to a
+particular view on the object:
+
+  >>> another_view.url(herd, 'something')
+  'http://127.0.0.1/herd/something'
+
+It works properly in the face of non-ascii characters in URLs:
+
+  >>> url = another_view.url(herd, unicode('árgh', 'UTF-8'))
+  >>> url
+  'http://127.0.0.1/herd/%C3%A1rgh'
+  >>> import urllib
+  >>> expected = unicode('http://127.0.0.1/herd/árgh', 'UTF-8')
+  >>> urllib.unquote(url).decode('utf-8') == expected
+  True
+
+It's also possible to just pass in a name. In this case, a URL to that
+view on the context object will be constructed:
+
+  >>> another_view.url('yet_another_view')
+  'http://127.0.0.1/herd/manfred/yet_another_view'
+
+Some combinations of arguments just don't make sense:
+
+  >>> another_view.url('foo', 'bar')
+  Traceback (most recent call last):
+    ...
+  TypeError: url() takes either obj argument, obj, string arguments, or
+  string argument
+  >>> another_view.url('foo', herd)
+  Traceback (most recent call last):
+    ...
+  TypeError: url() takes either obj argument, obj, string arguments, or
+  string argument
+  >>> another_view.url(herd, 'bar', 'baz')
+  Traceback (most recent call last):
+    ...
+  TypeError: url() takes at most 3 arguments (4 given)
+  
+"""
+import grok
+
+class Herd(grok.Container, grok.Model):
+    pass
+
+class Mammoth(grok.Model):
+    pass
+
+grok.context(Mammoth)
+
+class Index(grok.View):
+    def render(self):
+        return self.url()
+    
+class Another(grok.View):
+    def render(self):
+        return self.url()
+
+class YetAnother(grok.View):
+    pass
+
+yetanother = grok.PageTemplate('<p tal:replace="view/url" />')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/url.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/url_function.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/url_function.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/url_function.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,84 @@
+# -*- coding: UTF-8 -*-
+"""
+There is a url function that can be imported from grok to determine the
+absolute URL of objects.
+
+  >>> from grok import url
+  >>> import grok
+  >>> grok.grok('grok.ftests.url.url_function')
+  
+  >>> from grok.ftests.url.url_function import Herd, Mammoth
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  >>> manfred = Mammoth()
+  >>> herd['manfred'] = manfred
+
+Now let's use url on some things::
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/herd/manfred/index")
+  >>> print browser.contents
+  http://localhost/herd/manfred/index
+  >>> browser.open("http://localhost/herd/manfred/another")
+  >>> print browser.contents
+  http://localhost/herd/manfred/another
+  
+We get the views manually so we can do a greater variety of url() calls:
+
+  >>> from zope import component
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> index_view = component.getMultiAdapter((manfred, request), name='index')
+  >>> url(request, index_view)
+  'http://127.0.0.1/herd/manfred/index'
+  >>> another_view = component.getMultiAdapter((manfred, request),
+  ...                                              name='another')
+  >>> url(request, another_view)
+  'http://127.0.0.1/herd/manfred/another'
+
+Now let's get a URL for a specific object:
+
+  >>> url(request, manfred)
+  'http://127.0.0.1/herd/manfred'
+
+We can get the URL for any object in content-space:
+
+  >>> url(request, herd)
+  'http://127.0.0.1/herd'
+
+We can also pass a name along with this, to generate a URL to a
+particular view on the object:
+
+  >>> url(request, herd, 'something')
+  'http://127.0.0.1/herd/something'
+
+It works properly in the face of non-ascii characters in URLs:
+
+  >>> u = url(request, herd, unicode('árgh', 'UTF-8'))
+  >>> u
+  'http://127.0.0.1/herd/%C3%A1rgh'
+  >>> import urllib
+  >>> expected = unicode('http://127.0.0.1/herd/árgh', 'UTF-8')
+  >>> urllib.unquote(u).decode('utf-8') == expected
+  True
+"""
+import grok
+from grok import url
+
+class Herd(grok.Container, grok.Model):
+    pass
+
+class Mammoth(grok.Model):
+    pass
+
+grok.context(Mammoth)
+
+class Index(grok.View):
+    def render(self):
+        return url(self.request, self)
+    
+class Another(grok.View):
+    def render(self):
+        return url(self.request, self)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/url/url_function.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/local.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/local.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/local.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,146 @@
+"""
+Local Utilities can be registered on subclasses of grok.Site using
+grok.local_utility:
+
+  >>> import grok
+  >>> from zope import component
+  >>> from grok.ftests.utility.local import *
+
+  >>> grok.grok('grok.ftests.utility.local')
+
+  >>> cave = Cave()
+  >>> getRootFolder()["cave"] = cave
+
+  >>> from zope.app.component.hooks import getSite, setSite
+  >>> setSite(cave)
+  
+  >>> fireplace = component.getUtility(IFireplace)
+  >>> IFireplace.providedBy(fireplace)
+  True
+  >>> isinstance(fireplace, Fireplace)
+  True
+  
+  >>> club = component.getUtility(IClub)
+  >>> IClub.providedBy(club)
+  True
+  >>> isinstance(club, Club)
+  True
+
+  >>> spiky = component.getUtility(IClub, name='spiky')
+  >>> IClub.providedBy(spiky)
+  True
+  >>> isinstance(spiky, SpikyClub)
+  True
+
+  >>> mammoth = component.getUtility(IMammoth)
+  >>> IMammoth.providedBy(mammoth)
+  True
+  >>> isinstance(mammoth, Mammoth)
+  True
+
+  >>> tiger = component.getUtility(IMammoth, name='tiger')
+  >>> IMammoth.providedBy(tiger)
+  True
+  >>> isinstance(tiger, SabretoothTiger)
+  True
+
+  >>> painting = component.getUtility(IPainting, name='blackandwhite')
+  >>> IPainting.providedBy(painting)
+  True
+  >>> isinstance(painting, CavePainting)
+  True
+
+  >>> colored = component.getUtility(IPainting, name='color')
+  >>> IPainting.providedBy(colored)
+  True
+  >>> isinstance(colored, ColoredCavePainting)
+  True
+
+Since it is a local utility, it is not available outside its site:
+
+  >>> setSite(None)
+  >>> component.getUtility(IFireplace)
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IFireplace>, '')
+
+  >>> component.getUtility(IClub)
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IClub>, '')
+
+  >>> component.getUtility(IClub, name='spiky')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IClub>, 'spiky')
+
+  >>> component.getUtility(IMammoth)
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IMammoth>, '')
+
+  >>> component.getUtility(IMammoth, name='tiger')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IMammoth>, 'tiger')
+
+  >>> component.getUtility(IPainting, name='blackandwhite')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IPainting>, 'blackandwhite')
+
+  >>> component.getUtility(IPainting, name='color')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.local.IPainting>, 'color')
+"""
+import grok
+from zope import interface
+import persistent
+
+class IFireplace(interface.Interface):
+    pass
+
+class IClub(interface.Interface):
+    pass
+
+class ISpiky(interface.Interface):
+    pass
+
+class IMammoth(interface.Interface):
+    pass
+
+class Fireplace(grok.LocalUtility):
+    grok.implements(IFireplace)
+
+class Club(object):
+    grok.implements(IClub)
+
+class SpikyClub(object):
+    grok.implements(IClub, ISpiky)
+
+class Mammoth(grok.LocalUtility):
+    grok.implements(IMammoth, IClub)
+
+class SabretoothTiger(grok.LocalUtility):
+    grok.implements(IMammoth, IClub)
+    grok.provides(IMammoth)
+
+class IPainting(persistent.interfaces.IPersistent):
+    pass
+
+class CavePainting(grok.LocalUtility):
+    grok.implements(IPainting)
+
+class ColoredCavePainting(grok.LocalUtility):
+    grok.implements(IPainting)
+    grok.provides(IPainting)
+
+class Cave(grok.Model, grok.Site):
+    grok.local_utility(Fireplace)
+    grok.local_utility(Club)
+    grok.local_utility(SpikyClub, provides=IClub, name='spiky')
+    grok.local_utility(Mammoth, provides=IMammoth)
+    grok.local_utility(SabretoothTiger, name='tiger')
+    grok.local_utility(CavePainting, name='blackandwhite', provides=IPainting)
+    grok.local_utility(ColoredCavePainting, name='color')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/local.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/local_override.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/local_override.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/local_override.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,44 @@
+"""
+Local Utilities can be registered on subclasses of grok.Site using
+grok.local_utility:
+
+  >>> import grok
+  >>> from zope import component
+  >>> from grok.ftests.utility.local_override import *
+
+  >>> grok.grok('grok.ftests.utility.local_override')
+
+  >>> cave = SpikyCave()
+  >>> getRootFolder()['cave'] = cave
+
+  >>> from zope.app.component.hooks import getSite, setSite
+  >>> setSite(cave)
+
+  >>> club = component.getUtility(IClub)
+  >>> IClub.providedBy(club)
+  True
+  >>> isinstance(club, SpikyClub)
+  True
+
+  >>> list(cave.getSiteManager().keys())
+  [u'SpikyClub']
+"""
+import grok
+from zope import interface
+import persistent
+
+class IClub(interface.Interface):
+    pass
+
+class Club(grok.LocalUtility):
+    grok.implements(IClub)
+
+class SpikyClub(grok.LocalUtility):
+    grok.implements(IClub)
+
+class Cave(grok.Model, grok.Site):
+    grok.local_utility(Club)
+
+class SpikyCave(Cave):
+    grok.local_utility(SpikyClub)
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/local_override.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/multiple_class.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/multiple_class.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/multiple_class.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,33 @@
+"""
+When you try to register multiple classes with the same (interface, name)
+combination multiple times using grok.local_utility, we expect an error:
+
+  >>> import grok
+  >>> from zope import component
+  >>> from grok.ftests.utility.multiple_class import *
+
+  >>> grok.grok('grok.ftests.utility.multiple_class')
+  Traceback (most recent call last):
+    ...
+  GrokError: Conflicting local utility registration
+  <class 'grok.ftests.utility.multiple_class.Fireplace2'> in site
+  <class 'grok.ftests.utility.multiple_class.Cave'>.
+  Local utilities are registered multiple times for interface
+  <InterfaceClass grok.ftests.utility.multiple_class.IFireplace> and
+  name 'Foo'.  
+"""
+import grok
+from zope import interface
+
+class IFireplace(interface.Interface):
+    pass
+
+class Fireplace(grok.LocalUtility):
+    grok.implements(IFireplace)
+
+class Fireplace2(grok.LocalUtility):
+    grok.implements(IFireplace)
+    
+class Cave(grok.Model, grok.Site):
+    grok.local_utility(Fireplace, name='Foo')
+    grok.local_utility(Fireplace2, name='Foo')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/multiple_class.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/multiple_directive.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/multiple_directive.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/multiple_directive.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,33 @@
+"""
+When you call the grok.local_utility directive multiple times specifying
+the same (interface, name) combination, we expect an error:
+
+  >>> import grok
+  >>> from zope import component
+  >>> from grok.ftests.utility.multiple_directive import *
+
+  >>> grok.grok('grok.ftests.utility.multiple_directive')
+  Traceback (most recent call last):
+    ...
+  GrokError: Conflicting local utility registration
+  <class 'grok.ftests.utility.multiple_directive.Fireplace2'> in site
+  <class 'grok.ftests.utility.multiple_directive.Cave'>.
+  Local utilities are registered multiple times for interface
+  <InterfaceClass grok.ftests.utility.multiple_directive.IFireplace> and
+  name u''.  
+"""
+import grok
+from zope import interface
+
+class IFireplace(interface.Interface):
+    pass
+
+class Fireplace(grok.LocalUtility):
+    grok.implements(IFireplace)
+
+class Fireplace2(grok.LocalUtility):
+    grok.implements(IFireplace)
+    
+class Cave(grok.Model, grok.Site):
+    grok.local_utility(Fireplace, provides=IFireplace)
+    grok.local_utility(Fireplace2, provides=IFireplace)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/multiple_directive.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/public.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/public.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/public.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,45 @@
+"""
+By default, a utility is not in the public site; it's in ++etc++site. We can
+also specify the utility to be public. It will then be created in the container
+that is the site. The name the utility should have in the container can
+be controlled using name_in_container:
+
+  >>> import grok
+  >>> from zope import component
+  >>> from grok.ftests.utility.public import *
+  >>> grok.grok('grok.ftests.utility.public')
+
+  >>> cave = Cave()
+  >>> getRootFolder()["cave"] = cave
+
+  >>> from zope.app.component.hooks import getSite, setSite
+  >>> setSite(cave)
+  >>> cave['fireplace'] is component.getUtility(IFireplace)
+  True
+
+name_in_container can also be used for objects stored under the site manager
+(that is in ++etc++site):
+
+   >>> cave2 = Cave2()
+   >>> getRootFolder()['cave2'] = cave2
+   >>> setSite(cave2)
+   >>> (cave2.getSiteManager()['fireplace'] is
+   ...  component.getUtility(IFireplace))
+   True
+
+"""
+
+import grok
+from zope import interface
+
+class IFireplace(interface.Interface):
+    pass
+
+class Fireplace(grok.LocalUtility):
+    grok.implements(IFireplace)
+    
+class Cave(grok.Container, grok.Site):
+    grok.local_utility(Fireplace, public=True, name_in_container='fireplace')
+
+class Cave2(grok.Container, grok.Site):
+    grok.local_utility(Fireplace, public=False, name_in_container='fireplace')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/public.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/publicnoncontainer.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/publicnoncontainer.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/publicnoncontainer.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,26 @@
+"""
+You cannot use local_utility with 'public' set to True if the site class
+isn't a container:
+
+  >>> import grok
+  >>> from zope import component
+  >>> from grok.ftests.utility.publicnoncontainer import *
+  >>> grok.grok('grok.ftests.utility.publicnoncontainer')
+  Traceback (most recent call last):
+    ...
+  GrokError: Cannot set public to True with grok.local_utility as the site
+  (<class 'grok.ftests.utility.publicnoncontainer.Cave'>) is not a container.
+
+"""
+
+import grok
+from zope import interface
+
+class IFireplace(interface.Interface):
+    pass
+
+class Fireplace(grok.LocalUtility):
+    grok.implements(IFireplace)
+    
+class Cave(grok.Model, grok.Site):
+    grok.local_utility(Fireplace, public=True, name_in_container='fireplace')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/publicnoncontainer.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/subclass.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/subclass.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/subclass.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,106 @@
+"""
+Subclassed sites inherit all local utilities of their base classes:
+
+  >>> import grok
+  >>> from zope import component
+  >>> from grok.ftests.utility.subclass import *
+
+  >>> grok.grok('grok.ftests.utility.subclass')
+
+  >>> cave = BigCave()
+  >>> getRootFolder()["cave"] = cave
+
+  >>> from zope.app.component.hooks import getSite, setSite
+
+  >>> setSite(cave)
+  >>> fireplace = component.getUtility(IFireplace)
+  >>> IFireplace.providedBy(fireplace)
+  True
+  >>> isinstance(fireplace, Fireplace)
+  True
+
+Additional utilities can be registered in the subclass:
+  
+  >>> hollow = HollowCave()
+  >>> getRootFolder()["hollow"] = hollow
+
+  >>> setSite(hollow)
+  >>> fireplace = component.getUtility(IFireplace)
+  >>> IFireplace.providedBy(fireplace)
+  True
+  >>> isinstance(fireplace, Fireplace)
+  True
+
+  >>> painting = component.getUtility(IPainting)
+  >>> IPainting.providedBy(painting)
+  True
+  >>> isinstance(painting, Painting)
+  True
+
+Those do not influence the base class:
+
+  >>> setSite(cave)
+  >>> painting = component.getUtility(IPainting)
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.ftests.utility.subclass.IPainting>, '')
+
+This works various levels of inheritance deep:
+
+  >>> very_hollow = VeryHollowCave()
+  >>> getRootFolder()['very_hollow'] = very_hollow
+
+  >>> setSite(very_hollow)
+  >>> fireplace = component.getUtility(IFireplace)
+  >>> painting = component.getUtility(IPainting)
+  >>> great_painting = component.getUtility(IPainting, 'great')
+  >>> bad_painting = component.getUtility(IPainting, 'bad')
+
+And with inheritance hierarchies where a base class is inherited multiple
+times through different routes:
+
+  >>> scary = ScaryCave()
+  >>> getRootFolder()['scary'] = scary
+
+  >>> setSite(scary)
+  >>> fireplace = component.getUtility(IFireplace)
+  >>> painting = component.getUtility(IPainting)
+  >>> great_painting = component.getUtility(IPainting, 'great')
+  >>> bad_painting = component.getUtility(IPainting, 'bad')
+
+"""
+import grok
+from zope import interface
+
+class IFireplace(interface.Interface):
+    pass
+
+class IPainting(interface.Interface):
+    pass
+
+class Fireplace(grok.LocalUtility):
+    grok.implements(IFireplace)
+
+class Painting(grok.LocalUtility):
+    grok.implements(IPainting)
+
+class Cave(grok.Model, grok.Site):
+    # we use name_in_container here to prevent multiple registrations
+    # since storing the utilities multiple times under the same name
+    # would raise a DuplicationError
+    grok.local_utility(Fireplace, name_in_container='fireplace')
+
+class BigCave(Cave):
+    pass
+
+class HollowCave(Cave):
+    grok.local_utility(Painting)
+
+class VeryHollowCave(HollowCave):
+    grok.local_utility(Painting, name='great')
+    grok.local_utility(Painting, name='bad')
+
+# this cave subclasses from Cave twice
+class ScaryCave(VeryHollowCave, Cave):
+    pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/utility/subclass.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/argument.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/argument.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/argument.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,76 @@
+"""
+  >>> import grok
+  >>> from grok.ftests.view.argument import Mammoth
+  >>> grok.grok('grok.ftests.view.argument')
+  >>> getRootFolder()["manfred"] = Mammoth()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+
+Form variables such as GET parameters are dispatched to arguments of
+the render() method, should the method choose to take them:
+
+  >>> browser.open("http://localhost/manfred/render?message=Foo&another=Bar")
+  >>> print browser.contents
+  Message: Foo
+  Another: Bar
+
+Supplying more arguments than those specified has no effect:
+
+  >>> browser.open("http://localhost/manfred/render?message=There&another=Is&last=More")
+  >>> print browser.contents
+  Message: There
+  Another: Is
+
+If you don't supply all of the arguments, there will be a System Error:
+
+  >>> browser.open("http://localhost/manfred/render?message=Foo")
+  Traceback (most recent call last):
+  ...
+  TypeError: Missing argument to render(): another
+
+The same works with views that define update():
+
+  >>> browser.open("http://localhost/manfred/update?message=Foo&another=Bar")
+  >>> print browser.contents
+  Coming to us from update():
+  Message: Foo
+  Another: Bar
+
+  >>> browser.open("http://localhost/manfred/update?message=There&another=Is&last=More")
+  >>> print browser.contents
+  Coming to us from update():
+  Message: There
+  Another: Is
+
+  >>> browser.open("http://localhost/manfred/update?another=Bar")
+  Traceback (most recent call last):
+  ...
+  TypeError: Missing argument to update(): message
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class RenderWithArguments(grok.View):
+    grok.name('render')
+
+    def render(self, message, another):
+        return "Message: %s\nAnother: %s" % (message, another)
+
+class UpdateWithArguments(grok.View):
+    grok.name('update')
+    grok.template('update')
+
+    def update(self, message, another):
+        self.message = message
+        self.another = another
+
+update = grok.PageTemplate("""
+Coming to us from update():
+Message: <span tal:replace="view/message" />
+Another: <span tal:replace="view/another" />
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/argument.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/index.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/index.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/index.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,39 @@
+"""
+  >>> import grok
+  >>> from grok.ftests.view.index import Mammoth
+  >>> grok.grok('grok.ftests.view.index')
+  >>> getRootFolder()["manfred"] = Mammoth()
+
+The default view name for a model is 'index':
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/manfred")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, world!</h1>
+  <span>Blue</span>
+  <span>Blue</span>
+  </body>
+  </html>
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    teeth = u"Blue"
+
+class Index(grok.View):
+    pass
+
+index = grok.PageTemplate("""\
+<html>
+<body>
+<h1>Hello, world!</h1>
+<span tal:content="python:context.teeth">green</span>
+<span tal:content="context/teeth">green</span>
+</body>
+</html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/index.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/layer.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/layer.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/layer.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,70 @@
+"""
+  >>> import grok
+  >>> from grok.ftests.view.layer import Mammoth
+  >>> grok.grok('grok.ftests.view.layer')
+  >>> getRootFolder()["manfred"] = Mammoth()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/++skin++Basic/manfred/cavedrawings")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, world!</h1>
+  </body>
+  </html>
+  
+  >>> browser.open("http://localhost/++skin++Rotterdam/manfred/cavedrawings")
+  Traceback (most recent call last):
+  ...
+  NotFound: Object: <grok.ftests.view.layer.Mammoth object at ...>, name: u'cavedrawings'
+
+  >>> browser.open("http://localhost/++skin++Rotterdam/manfred/moredrawings")
+  >>> print browser.contents
+  Pretty
+
+  >>> browser.open("http://localhost/++skin++myskin/manfred/evenmoredrawings")
+  >>> print browser.contents
+  Awesome
+
+"""
+import grok
+from zope.app.basicskin import IBasicSkin
+from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.app.rotterdam import rotterdam
+from zope import interface
+
+grok.layer(IBasicSkin)
+
+class MySkinLayer(grok.ILayer):
+    pass
+
+class MySkin(grok.Skin):
+    grok.layer(MySkinLayer)
+
+class Mammoth(grok.Model):
+    pass
+
+class CaveDrawings(grok.View):
+    pass
+
+cavedrawings = grok.PageTemplate("""\
+<html>
+<body>
+<h1>Hello, world!</h1>
+</body>
+</html>
+""")
+
+class MoreDrawings(grok.View):
+    grok.layer(rotterdam)
+
+    def render(self):
+        return "Pretty"
+
+class EvenMoreDrawings(grok.View):
+    grok.layer(MySkinLayer)
+
+    def render(self):
+        return "Awesome"


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/layer.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/macros.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/macros.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/macros.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,96 @@
+"""
+  >>> import grok
+  >>> from grok.ftests.view.macros import Mammoth
+  >>> grok.grok('grok.ftests.view.macros')
+  >>> getRootFolder()["manfred"] = Mammoth()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/manfred/@@painting")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>GROK MACRO!</h1>
+  <div>
+  GROK SLOT!
+  </div>
+  </body>
+  </html>
+
+Views without a template do not support macros:
+
+  >>> browser.open("http://localhost/manfred/@@dancing")
+  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 
+shadows the view. XXX This should probably generate a warning at runtime.
+
+  >>> browser.open("http://localhost/manfred/@@grilldish")
+  >>> print browser.contents
+  <html>
+  Curry
+  </html>
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class DancingHall(grok.View):
+
+    def render(self):
+        return "A nice large dancing hall for mammoths."
+
+class Grilled(grok.View):
+
+    def update(self):
+        self.spices = "Pepper and salt"
+
+class Painting(grok.View):
+    pass
+
+painting = grok.PageTemplate("""\
+<html metal:use-macro="context/@@layout/main">
+<div metal:fill-slot="slot">
+GROK SLOT!
+</div>
+</html>
+""")
+
+class Layout(grok.View):
+    pass
+
+layout = grok.PageTemplate("""\
+<html metal:define-macro="main">
+<body>
+<h1>GROK MACRO!</h1>
+<div metal:define-slot="slot">
+</div>
+</body>
+</html>""")
+
+class Dancing(grok.View):
+    pass
+
+dancing = grok.PageTemplate("""\
+<html metal:use-macro="context/@@dancinghall/something">
+</html>
+""")
+
+class GrillDish(grok.View):
+    pass
+
+grilldish = grok.PageTemplate("""
+<html metal:use-macro="context/@@grilled/spices">
+</html>""")
+
+class Grilled(grok.View):
+    pass
+
+grilled = grok.PageTemplate("""\
+<html metal:define-macro="spices">
+Curry
+</html>""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/macros.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/view.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/view.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/view.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,33 @@
+"""
+  >>> import grok
+  >>> from grok.ftests.view.view import Mammoth
+  >>> grok.grok('grok.ftests.view.view')
+  >>> getRootFolder()["manfred"] = Mammoth()
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/manfred/@@painting")
+  >>> print browser.contents
+  <html>
+  <body>
+  <h1>Hello, world!</h1>
+  </body>
+  </html>
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class Painting(grok.View):
+    pass
+
+painting = grok.PageTemplate("""\
+<html>
+<body>
+<h1>Hello, world!</h1>
+</body>
+</html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/view/view.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc/xmlrpc.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc/xmlrpc.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc/xmlrpc.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,29 @@
+"""
+  >>> import grok
+  >>> grok.grok('grok.ftests.xmlrpc.xmlrpc')
+  >>> from grok.ftests.xmlrpc.xmlrpc import Mammoth
+  >>> getRootFolder()["Manfred"] = Mammoth()
+
+  >>> from grok.ftests.xmlrpc_helper import ServerProxy
+
+  >>> server = ServerProxy("http://localhost/")
+  >>> server.Manfred.stomp()
+  'Manfred stomped.'
+  >>> server.Manfred.dance()
+  "Manfred doesn't like to dance."
+
+"""
+import grok
+
+
+class Mammoth(grok.Model):
+    pass
+
+
+class MammothRPC(grok.XMLRPC):
+
+    def stomp(self):
+        return '%s stomped.' % self.context.__name__
+
+    def dance(self):
+        return '%s doesn\'t like to dance.' % self.context.__name__


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc/xmlrpc.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc_helper.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc_helper.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc_helper.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,77 @@
+# XXX This code is duplicated from Zope 3 trunk (future Zope 3.4) as we want to
+# stay compatible with Zope 3.3
+#
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""XMLRPC testing helpers for Zope 3.
+
+$Id$
+"""
+
+import StringIO
+import xmlrpclib 
+
+from zope.app.testing.functional import HTTPCaller
+
+
+class ZopeTestTransport(xmlrpclib.Transport):
+    """xmlrpclib transport that delegates to
+    zope.app.testing.functional.HTTPCaller.
+
+    It can be used like a normal transport, including support for basic
+    authentication.
+    """
+
+    verbose = False
+    handleErrors = True
+
+    def request(self, host, handler, request_body, verbose=0):
+        request = "POST %s HTTP/1.0\n" % (handler,)
+        request += "Content-Length: %i\n" % len(request_body)
+        request += "Content-Type: text/xml\n"
+
+        host, extra_headers, x509 = self.get_host_info(host)
+        if extra_headers:
+            request += "Authorization: %s\n" \
+                       % (dict(extra_headers)["Authorization"],)
+
+        request += "\n" + request_body
+        response = HTTPCaller()(request, handle_errors=self.handleErrors)
+
+        errcode = response.getStatus()
+        errmsg = response.getStatusString()
+        # This is not the same way that the normal transport deals
+        # with the headers.
+        headers = response.getHeaders()
+
+        if errcode != 200:
+            raise xmlrpclib.ProtocolError(
+                host + handler,
+                errcode, errmsg,
+                headers
+                )
+
+        return self._parse_response(
+            StringIO.StringIO(response.getBody()), sock=None)
+
+
+def ServerProxy(uri, transport=ZopeTestTransport(), encoding=None,
+                verbose=0, allow_none=0, handleErrors=True):
+    """A factory that creates a server proxy using the ZopeTestTransport
+    by default.
+    
+    """
+    if isinstance(transport, ZopeTestTransport):
+        transport.handleErrors = handleErrors
+    return xmlrpclib.ServerProxy(uri, transport, encoding, verbose, allow_none)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/ftests/xmlrpc_helper.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/index.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/index.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/index.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,56 @@
+import sys
+
+from zope.interface import implements
+from zope.interface.interfaces import IMethod, IInterface
+
+from zope.app.catalog.field import FieldIndex
+from zope.app.catalog.text import TextIndex
+
+from martian.error import GrokError, GrokImportError
+from martian.util import frame_is_class
+
+from grok.interfaces import IIndexDefinition
+
+class IndexDefinition(object):
+    implements(IIndexDefinition)
+
+    index_class = None
+
+    def __init__(self, *args, **kw):
+        frame = sys._getframe(1)
+        if not frame_is_class(frame):
+            raise GrokImportError(
+                "%r can only be instantiated on class level." % self.__class__)
+        # store any extra parameters to pass to index later
+        self._args = args
+        self._attribute = kw.pop('attribute', None)
+        self._kw = kw
+
+    def setup(self, catalog, name, context, module_info):
+        if self._attribute is not None:
+            field_name = self._attribute
+        else:
+            field_name = name
+
+        if IInterface.providedBy(context):
+            try:
+                method = context[field_name]
+            except KeyError:
+                raise GrokError("grok.Indexes in %r refers to an attribute or "
+                                "method %r on interface %r, but this does not "
+                                "exist." % (module_info.getModule(),
+                                            field_name, context), None)
+            call = IMethod.providedBy(method)
+        else:
+            call = callable(getattr(context, field_name, None))
+            context = None # no interface lookup
+        catalog[name] = self.index_class(field_name=field_name,
+                                         interface=context,
+                                         field_callable=call,
+                                         *self._args, **self._kw)
+
+class Field(IndexDefinition):
+    index_class = FieldIndex
+
+class Text(IndexDefinition):
+    index_class = TextIndex


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/index.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/interfaces.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/interfaces.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/interfaces.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,430 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Grok interfaces
+"""
+from zope import interface, schema
+from zope.publisher.interfaces.browser import IBrowserPage
+from zope.formlib.interfaces import reConstraint
+
+class IGrokBaseClasses(interface.Interface):
+    ClassGrokker = interface.Attribute("Base class to define a class "
+                                       "grokker.")
+    InstanceGrokker = interface.Attribute("Base class to define an "
+                                          "instance grokker.")
+    ModuleGrokker = interface.Attribute("Base class to define a "
+                                        "module grokker.")
+    Model = interface.Attribute("Base class for persistent content objects "
+                                "(models).")
+    Container = interface.Attribute("Base class for containers.")
+    Site = interface.Attribute("Mixin class for sites.")
+    Application = interface.Attribute("Base class for applications.")
+    Adapter = interface.Attribute("Base class for adapters.")
+    MultiAdapter = interface.Attribute("Base class for multi-adapters.")
+    Annotation = interface.Attribute("Base class for persistent annotations.")
+    GlobalUtility = interface.Attribute("Base class for global utilities.")
+    LocalUtility = interface.Attribute("Base class for local utilities.")
+    View = interface.Attribute("Base class for browser views.")
+    XMLRPC = interface.Attribute("Base class for XML-RPC methods.")
+    Traverser = interface.Attribute("Base class for custom traversers.")
+    Form = interface.Attribute("Base class for forms.")
+    AddForm = interface.Attribute("Base class for add forms.")
+    EditForm = interface.Attribute("Base class for edit forms.")
+    DisplayForm = interface.Attribute("Base class for display forms.")
+    Indexes = interface.Attribute("Base class for catalog index definitions.")
+    ILayer = interface.Attribute("Base interface for layers.")
+    Skin = interface.Attribute("Base class for skin.")
+
+
+class IGrokErrors(interface.Interface):
+
+    def GrokError(message, component):
+        """Error indicating that a problem occurrend during the
+        grokking of a module (at "grok time")."""
+
+    def GrokImportError(*args):
+        """Error indicating a problem at import time."""
+
+
+class IGrokDirectives(interface.Interface):
+
+    def implements(*interfaces):
+        """Declare that a class implements the given interfaces."""
+
+    def adapts(*classes_or_interfaces):
+        """Declare that a class adapts objects of the given classes or
+        interfaces."""
+
+    def context(class_or_interface):
+        """Declare the context for views, adapters, etc.
+
+        This directive can be used on module and class level.  When
+        used on module level, it will set the context for all views,
+        adapters, etc. in that module.  When used on class level, it
+        will set the context for that particular class."""
+
+    def name(name):
+        """Declare the name of a view or adapter/multi-adapter.
+
+        This directive can only be used on class level."""
+
+    def layer(layer):
+        """Declare the layer for the view.
+
+        This directive acts as a contraint on the 'request' of
+        grok.View. This directive can only be used on class level."""
+
+    def skin(skin):
+        """Declare this layer as a named skin.
+
+        This directive can only be used on class level."""
+
+    def template(template):
+        """Declare the template name for a view.
+
+        This directive can only be used on class level."""
+
+    def templatedir(directory):
+        """Declare a directory to be searched for templates.
+
+        By default, grok will take the name of the module as the name
+        of the directory.  This can be overridden using
+        ``templatedir``."""
+
+    def provides(interface):
+        """Explicitly specify with which interface a component will be
+        looked up."""
+
+    def baseclass():
+        """Mark this class as a base class.
+
+        This means it won't be grokked, though if it's a possible context,
+        it can still serve as a context.
+        """
+
+    def global_utility(factory, provides=None, name=u''):
+        """Register a global utility.
+
+        factory - the factory that creates the global utility
+        provides - the interface the utility should be looked up with
+        name - the name of the utility
+        """
+
+    def local_utility(factory, provides=None, name=u'',
+                      setup=None, public=False, name_in_container=None):
+        """Register a local utility.
+
+        factory - the factory that creates the local utility
+        provides - the interface the utility should be looked up with
+        name - the name of the utility
+        setup - a callable that receives the utility as its single argument,
+                it is called after the utility has been created and stored
+        public - if False, the utility will be stored below ++etc++site
+                 if True, the utility will be stored directly in the site.
+                 The site should in this case be a container.
+        name_in_container - the name to use for storing the utility
+        """
+
+    def define_permission(permission):
+        """Defines a new permission with the id ``permission``."""
+
+    def require(permission):
+        """Protect a view class or an XMLRPC method with ``permision``.
+
+        ``permission`` must already be defined, e.g. using
+        grok.define_permission.
+
+        grok.require can be used as a class-level directive or as a
+        method decorator."""
+
+    def site(class_or_interface):
+        """Specifies the site that an indexes definition is for.
+
+        It can only be used inside grok.Indexes subclasses.
+        """
+
+
+class IGrokDecorators(interface.Interface):
+
+    def subscribe(*classes_or_interfaces):
+        """Declare that a function subscribes to an event or a
+        combination of objects and events."""
+
+    def action(label, **options):
+        """Decorator that defines an action factory based on a form
+        method. The method receives the form data as keyword
+        parameters."""
+
+
+class IGrokEvents(interface.Interface):
+
+    IObjectCreatedEvent = interface.Attribute("")
+
+    ObjectCreatedEvent = interface.Attribute("")
+
+    IObjectModifiedEvent = interface.Attribute("")
+
+    ObjectModifiedEvent = interface.Attribute("")
+
+    IObjectCopiedEvent = interface.Attribute("")
+
+    ObjectCopiedEvent = interface.Attribute("")
+
+    IObjectAddedEvent = interface.Attribute("")
+
+    ObjectAddedEvent = interface.Attribute("")
+
+    IObjectMovedEvent = interface.Attribute("")
+
+    ObjectMovedEvent = interface.Attribute("")
+
+    IObjectRemovedEvent = interface.Attribute("")
+
+    ObjectRemovedEvent = interface.Attribute("")
+
+    IContainerModifiedEvent = interface.Attribute("")
+
+    ContainerModifiedEvent = interface.Attribute("")
+
+
+class IGrokAPI(IGrokBaseClasses, IGrokDirectives, IGrokDecorators,
+               IGrokEvents, IGrokErrors):
+
+    def grok(dotted_name):
+        """Grok a module or package specified by ``dotted_name``."""
+
+    def grok_component(name, component, context=None, module_info=None,
+                       templates=None):
+        """Grok an arbitrary object. Can be useful during testing.
+
+        name - the name of the component (class name, or global instance name
+               as it would appear in a module).
+        component - the object (class, etc) to grok.
+        context - the context object (optional).
+        module_info - the module being grokked (optional).
+        templates - the templates registry (optional).
+
+        Note that context, module_info and templates might be required
+        for some grokkers which rely on them.
+        """
+    
+    def url(request, obj, name=None):
+        """Generate the URL to an object with optional name attached.
+        """
+
+    def notify(event):
+        """Send ``event`` to event subscribers."""
+
+    def getSite():
+        """Get the current site."""
+
+    def PageTemplate(template):
+        """Create a Grok PageTemplate object from ``template`` source
+        text.  This can be used for inline PageTemplates."""
+
+    def PageTemplateFile(filename):
+        """Create a Grok PageTemplate object from a file specified by
+        ``filename``.  It will be treated like an inline template
+        created with ``PageTemplate``."""
+
+    def Fields(*args, **kw):
+        """Return a list of formlib fields based on interfaces and/or schema
+        fields."""
+
+    def AutoFields(context):
+        """Return a list of fields for context autogenerated by grok.
+        """
+
+    def action(label, actions=None, **options):
+        """grok-specific action decorator.
+        """
+
+
+class IGrokView(IBrowserPage):
+    """Grok views all provide this interface.
+    """
+
+    context = interface.Attribute('context', "Object that the view presents.")
+
+    request = interface.Attribute('request', "Request that the view was looked"
+                                  "up with.")
+
+    response = interface.Attribute('response', "Response object that is "
+                                   "associated with the current request.")
+
+    static = interface.Attribute('static', "Directory resource containing "
+                                 "the static files of the view's package.")
+
+    def redirect(url):
+       """Redirect to given URL"""
+
+    def url(obj=None, name=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.
+        """
+
+    def 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)."""
+
+    def 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)."""
+
+    def 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.
+        """
+
+
+class IGrokForm(IGrokView):
+    """Grok form API, inspired by zope.formlib's IFormBaseCustomization.
+
+    We explicitly don't inherit from IFormBaseCustomization because
+    that would imply ISubPage with another definition of update() and
+    render() than IGrokView has.
+    """
+
+    prefix = schema.ASCII(
+        constraint=reConstraint(
+            '[a-zA-Z][a-zA-Z0-9_]*([.][a-zA-Z][a-zA-Z0-9_]*)*',
+            "Must be a sequence of not-separated identifiers"),
+        description=u"""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.
+        """,
+        readonly=True,
+        )
+
+    def setPrefix(prefix):
+        """Update the subpage prefix
+        """
+
+    label = interface.Attribute("A label to display at the top of a form")
+
+    status = interface.Attribute(
+        """An update status message
+
+        This is normally generated by success or failure handlers.
+        """)
+
+    errors = interface.Attribute(
+        """Sequence of errors encountered during validation
+        """)
+
+    form_result = interface.Attribute(
+        """Return from action result method
+        """)
+
+    form_reset = interface.Attribute(
+        """Boolean indicating whether the form needs to be reset
+        """)
+
+    form_fields = interface.Attribute(
+        """The form's form field definitions
+
+        This attribute is used by many of the default methods.
+        """)
+
+    widgets = interface.Attribute(
+        """The form's widgets
+
+        - set by setUpWidgets
+
+        - used by validate
+        """)
+
+    def 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.
+        """
+
+    def 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.
+        """
+
+    template = interface.Attribute(
+        """Template used to display the form
+        """)
+
+    def resetForm():
+        """Reset any cached data because underlying content may have changed
+        """
+
+    def error_views():
+        """Return views of any errors.
+
+        The errors are returned as an iterable.
+        """
+
+    def 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 IApplication(interface.Interface):
+    """Marker-interface for grok application factories.
+
+    Used to register applications as utilities to look them up and
+    provide a list of grokked applications.
+    """
+
+class IIndexDefinition(interface.Interface):
+    """Define an index for grok.Indexes.
+    """
+
+    def setup(catalog, name, context):
+        """Set up index called name in given catalog.
+
+        Use name for index name and attribute to index. Set up
+        index for interface or class context.
+        """
+    
+        


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/meta.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/meta.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/meta.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,601 @@
+import os
+
+import zope.component.interface
+from zope import interface, component
+from zope.publisher.interfaces.browser import (IDefaultBrowserLayer,
+                                               IBrowserRequest,
+                                               IBrowserPublisher,
+                                               IBrowserSkinType)
+from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
+from zope.security.permission import Permission
+from zope.security.interfaces import IPermission
+from zope.annotation.interfaces import IAnnotations
+
+from zope.app.publisher.xmlrpc import MethodPublisher
+from zope.app.container.interfaces import IContainer
+from zope.app.container.interfaces import INameChooser
+from zope.app.container.contained import contained
+
+from zope.app.intid import IntIds
+from zope.app.intid.interfaces import IIntIds
+from zope.app.catalog.catalog import Catalog
+from zope.app.catalog.interfaces import ICatalog
+
+from zope.exceptions.interfaces import DuplicationError
+
+import martian
+from martian.error import GrokError
+from martian import util
+
+import grok
+from grok import components, formlib
+from grok.util import check_adapts, get_default_permission, make_checker
+
+class ModelGrokker(martian.ClassGrokker):
+    component_class = grok.Model
+
+    def grok(self, name, factory, context, module_info, templates):
+        for field in formlib.get_context_schema_fields(factory):
+            setattr(factory, field.__name__, field.default)
+        return True
+
+class ContainerGrokker(ModelGrokker):
+    component_class = grok.Container
+
+
+class LocalUtilityGrokker(ModelGrokker):
+    component_class = grok.LocalUtility
+
+
+class AdapterGrokker(martian.ClassGrokker):
+    component_class = grok.Adapter
+
+    def grok(self, name, factory, context, module_info, templates):
+        adapter_context = util.determine_class_context(factory, context)
+        provides = util.class_annotation(factory, 'grok.provides', None)
+        if provides is None:
+            util.check_implements_one(factory)
+        name = util.class_annotation(factory, 'grok.name', '')
+        component.provideAdapter(factory, adapts=(adapter_context,),
+                                 provides=provides,
+                                 name=name)
+        return True
+        
+class MultiAdapterGrokker(martian.ClassGrokker):
+    component_class = grok.MultiAdapter
+
+    def grok(self, name, factory, context, module_info, templates):
+        provides = util.class_annotation(factory, 'grok.provides', None)
+        if provides is None:
+            util.check_implements_one(factory)
+        check_adapts(factory)
+        name = util.class_annotation(factory, 'grok.name', '')
+        component.provideAdapter(factory, provides=provides, name=name)
+        return True
+
+class GlobalUtilityGrokker(martian.ClassGrokker):
+    component_class = grok.GlobalUtility
+
+    def grok(self, name, factory, context, module_info, templates):
+        provides = util.class_annotation(factory, 'grok.provides', None)
+        if provides is None:
+            util.check_implements_one(factory)
+        name = util.class_annotation(factory, 'grok.name', '')
+        component.provideUtility(factory(), provides=provides, name=name)
+        return True
+
+class XMLRPCGrokker(martian.ClassGrokker):
+    component_class = grok.XMLRPC
+
+    def grok(self, name, factory, context, module_info, templates):
+        view_context = util.determine_class_context(factory, context)
+        # XXX We should really not make __FOO__ methods available to
+        # the outside -- need to discuss how to restrict such things.
+        methods = util.methods_from_class(factory)
+
+        default_permission = get_default_permission(factory)
+        
+        for method in methods:
+            # Make sure that the class inherits MethodPublisher, so that the
+            # views have a location
+            method_view = type(
+                factory.__name__, (factory, MethodPublisher),
+                {'__call__': method}
+                )
+            component.provideAdapter(
+                method_view, (view_context, IXMLRPCRequest),
+                interface.Interface,
+                name=method.__name__)
+
+            # Protect method_view with either the permission that was
+            # set on the method, the default permission from the class
+            # level or zope.Public.
+            permission = getattr(method, '__grok_require__',
+                                 default_permission)
+            make_checker(factory, method_view, permission)
+        return True
+    
+class ViewGrokker(martian.ClassGrokker):
+    component_class = grok.View
+
+    def grok(self, name, factory, context, module_info, templates):
+        view_context = util.determine_class_context(factory, context)
+
+        factory.module_info = module_info
+        factory_name = factory.__name__.lower()
+
+        if util.check_subclass(factory, components.GrokForm):
+            # setup form_fields from context class if we've encountered a form
+            if getattr(factory, 'form_fields', None) is None:
+                factory.form_fields = formlib.get_auto_fields(view_context)
+
+            if not getattr(factory.render, 'base_method', False):
+                raise GrokError(
+                    "It is not allowed to specify a custom 'render' "
+                    "method for form %r. Forms either use the default "
+                    "template or a custom-supplied one." % factory,
+                    factory)
+
+        # find templates
+        template_name = util.class_annotation(factory, 'grok.template',
+                                              factory_name)
+        template = templates.get(template_name)
+
+        if factory_name != template_name:
+            # grok.template is being used
+            if templates.get(factory_name):
+                raise GrokError("Multiple possible templates for view %r. It "
+                                "uses grok.template('%s'), but there is also "
+                                "a template called '%s'."
+                                % (factory, template_name, factory_name),
+                                factory)
+
+        if template:
+            if (getattr(factory, 'render', None) and not
+                util.check_subclass(factory, components.GrokForm)):
+                # we do not accept render and template both for a view
+                # (unless it's a form, they happen to have render.
+                raise GrokError(
+                    "Multiple possible ways to render view %r. "
+                    "It has both a 'render' method as well as "
+                    "an associated template." % factory, factory)
+
+            templates.markAssociated(template_name)
+            factory.template = template
+        else:
+            if not getattr(factory, 'render', None):
+                # we do not accept a view without any way to render it
+                raise GrokError("View %r has no associated template or "
+                                "'render' method." % factory, factory)
+
+        view_layer = util.class_annotation(factory, 'grok.layer',
+                                           None) or module_info.getAnnotation('grok.layer',
+                                               None) or IDefaultBrowserLayer
+
+        view_name = util.class_annotation(factory, 'grok.name',
+                                          factory_name)
+        # __view_name__ is needed to support IAbsoluteURL on views
+        factory.__view_name__ = view_name
+        component.provideAdapter(factory,
+                                 adapts=(view_context, view_layer),
+                                 provides=interface.Interface,
+                                 name=view_name)
+
+        # protect view, public by default
+        default_permission = get_default_permission(factory)
+        make_checker(factory, factory, default_permission)
+    
+        # safety belt: make sure that the programmer didn't use
+        # @grok.require on any of the view's methods.
+        methods = util.methods_from_class(factory)
+        for method in methods:
+            if getattr(method, '__grok_require__', None) is not None:
+                raise GrokError('The @grok.require decorator is used for '
+                                'method %r in view %r. It may only be used '
+                                'for XML-RPC methods.'
+                                % (method.__name__, factory), factory)
+        return True
+    
+
+class JSONGrokker(martian.ClassGrokker):
+    component_class = grok.JSON
+
+    def grok(self, name, factory, context, module_info, templates):
+        view_context = util.determine_class_context(factory, context)
+        methods = util.methods_from_class(factory)
+
+        default_permission = get_default_permission(factory)
+        
+        for method in methods:
+            # Create a new class with a __view_name__ attribute so the
+            # JSON class knows what method to call.
+            method_view = type(
+                factory.__name__, (factory,),
+                {'__view_name__': method.__name__}
+                )
+            component.provideAdapter(
+                method_view, (view_context, IDefaultBrowserLayer),
+                interface.Interface,
+                name=method.__name__)
+
+            # Protect method_view with either the permission that was
+            # set on the method, the default permission from the class
+            # level or zope.Public.
+
+            permission = getattr(method, '__grok_require__',
+                                 default_permission)
+            make_checker(factory, method_view, permission)
+        return True
+    
+class TraverserGrokker(martian.ClassGrokker):
+    component_class = grok.Traverser
+
+    def grok(self, name, factory, context, module_info, templates):
+        factory_context = util.determine_class_context(factory, context)
+        component.provideAdapter(factory,
+                                 adapts=(factory_context, IBrowserRequest),
+                                 provides=IBrowserPublisher)
+        return True
+    
+class ModulePageTemplateGrokker(martian.InstanceGrokker):
+    # this needs to happen before any other grokkers execute that actually
+    # use the templates
+    priority = 1000
+
+    component_class = grok.PageTemplate
+    
+    def grok(self, name, instance, context, module_info, templates):
+        templates.register(name, instance)
+        instance._annotateGrokInfo(name, module_info.dotted_name)
+        return True
+
+class ModulePageTemplateFileGrokker(ModulePageTemplateGrokker):
+    priority = 1000
+    component_class = grok.PageTemplateFile
+
+class FilesystemPageTemplateGrokker(martian.GlobalGrokker):
+    # do this early on, but after ModulePageTemplateGrokker, as
+    # findFilesystem depends on module-level templates to be
+    # already grokked for error reporting
+    priority = 999
+
+    def grok(self, name, module, context, module_info, templates):
+        templates.findFilesystem(module_info)
+        return True
+
+class SubscriberGrokker(martian.GlobalGrokker):
+
+    def grok(self, name, module, context, module_info, templates):
+        subscribers = module_info.getAnnotation('grok.subscribers', [])
+
+        for factory, subscribed in subscribers:
+            component.provideHandler(factory, adapts=subscribed)
+            for iface in subscribed:
+                zope.component.interface.provideInterface('', iface)
+        return True
+
+class StaticResourcesGrokker(martian.GlobalGrokker):
+
+    def grok(self, name, module, context, module_info, templates):
+        # we're only interested in static resources if this module
+        # happens to be a package
+        if not module_info.isPackage():
+            return False
+
+        resource_path = module_info.getResourcePath('static')
+        if os.path.isdir(resource_path):
+            static_module = module_info.getSubModuleInfo('static')
+            if static_module is not None:
+                if static_module.isPackage():
+                    raise GrokError(
+                        "The 'static' resource directory must not "
+                        "be a python package.",
+                        module_info.getModule())
+                else:
+                    raise GrokError(
+                        "A package can not contain both a 'static' "
+                        "resource directory and a module named "
+                        "'static.py'", module_info.getModule())
+
+        resource_factory = components.DirectoryResourceFactory(
+            resource_path, module_info.dotted_name)
+        component.provideAdapter(
+            resource_factory, (IDefaultBrowserLayer,),
+            interface.Interface, name=module_info.dotted_name)
+        return True
+
+class GlobalUtilityDirectiveGrokker(martian.GlobalGrokker):
+
+    def grok(self, name, module, context, module_info, templates):
+        infos = module_info.getAnnotation('grok.global_utility', [])
+
+        for info in infos:
+            if info.provides is None:
+                util.check_implements_one(info.factory)
+            if info.direct:
+                obj = info.factory
+            else:
+                obj = info.factory()
+            component.provideUtility(obj,
+                                     provides=info.provides,
+                                     name=info.name)
+        return True
+
+class SiteGrokker(martian.ClassGrokker):
+    component_class = grok.Site
+    priority = 500
+
+    def grok(self, name, factory, context, module_info, templates):
+        infos = util.class_annotation_list(factory, 'grok.local_utility', None)
+        if infos is None:
+            return False
+
+        for info in infos:
+            if info.public and not IContainer.implementedBy(factory):
+                raise GrokError(
+                    "Cannot set public to True with grok.local_utility as "
+                    "the site (%r) is not a container." %
+                    factory, factory)
+            if info.provides is None:
+                if util.check_subclass(info.factory, grok.LocalUtility):
+                    baseInterfaces = interface.implementedBy(grok.LocalUtility)
+                    utilityInterfaces = interface.implementedBy(info.factory)
+                    provides = list(utilityInterfaces - baseInterfaces)
+
+                    if len(provides) == 0 and len(list(utilityInterfaces)) > 0:
+                        raise GrokError(
+                            "Cannot determine which interface to use "
+                            "for utility registration of %r in site %r. "
+                            "It implements an interface that is a specialization "
+                            "of an interface implemented by grok.LocalUtility. "
+                            "Specify the interface by either using grok.provides "
+                            "on the utility or passing 'provides' to "
+                            "grok.local_utility." % (info.factory, factory),
+                            info.factory)
+                else:
+                    provides = list(interface.implementedBy(info.factory))
+
+                util.check_implements_one_from_list(provides, info.factory)
+                info.provides = provides[0]
+
+        # raise an error in case of any duplicate registrations
+        # on the class level (subclassing overrides, see below)
+        used = set()
+        class_infos = util.class_annotation(factory, 'grok.local_utility',
+                                            [])
+        for info in class_infos:
+            key = (info.provides, info.name)
+            if key in used:
+                raise GrokError(
+                    "Conflicting local utility registration %r in "
+                    "site %r. Local utilities are registered multiple "
+                    "times for interface %r and name %r." %
+                    (info.factory, factory, info.provides, info.name),
+                    factory)
+            used.add(key)
+
+        # Make sure that local utilities from subclasses override
+        # utilities from base classes if the registration (provided
+        # interface, name) is identical.
+        overridden_infos = []
+        used = set()
+        for info in reversed(infos):
+            key = (info.provides, info.name)
+            if key in used:
+                continue
+            used.add(key)
+            overridden_infos.append(info)
+        overridden_infos.reverse()
+
+        # store infos on site class
+        factory.__grok_utilities_to_install__ = overridden_infos
+        component.provideHandler(localUtilityRegistrationSubscriber,
+                                 adapts=(factory, grok.IObjectAddedEvent))
+
+        return True
+
+def localUtilityRegistrationSubscriber(site, event):
+    """A subscriber that fires to set up local utilities.
+    """
+    installed = getattr(site, '__grok_utilities_installed__', False)
+    if installed:
+        return
+
+    for info in util.class_annotation(site.__class__,
+                                      'grok.utilities_to_install', []):
+        setupUtility(site, info.factory(), info.provides, name=info.name,
+                     name_in_container=info.name_in_container,
+                     public=info.public, setup=info.setup)
+
+    # we are done. If this subscriber gets fired again, we therefore
+    # do not register utilities anymore
+    site.__grok_utilities_installed__ = True
+
+def setupUtility(site, utility, provides, name=u'',
+                 name_in_container=None, public=False, setup=None):
+    """Set up a utility in a site.
+
+    site - the site to set up the utility in
+    utility - the utility to set up
+    provides - the interface the utility should be registered with
+    name - the name the utility should be registered under, default
+      the empty string (no name)
+    name_in_container - if given it will be used to add the utility
+      object to its container. Otherwise a name will be made up
+    public - if False, the utility will be stored in the site manager. If
+      True, the utility will be storedin the site (it is assumed the
+      site is a container)
+    setup - if not None, it will be called with the utility as its first
+       argument. This function can then be used to further set up the
+       utility.
+    """
+    site_manager = site.getSiteManager()
+
+    if not public:
+        container = site_manager
+    else:
+        container = site
+
+    if name_in_container is None:
+        name_in_container = INameChooser(container).chooseName(
+            utility.__class__.__name__, utility)
+    container[name_in_container] = utility
+
+    if setup is not None:
+        setup(utility)
+        
+    site_manager.registerUtility(utility, provided=provides,
+                                 name=name)
+    
+class DefinePermissionGrokker(martian.GlobalGrokker):
+
+    priority = 1500
+
+    def grok(self, name, module, context, module_info, templates):
+        permissions = module_info.getAnnotation('grok.define_permission', [])
+        for permission in permissions:
+            # IPermission.title says that permission ids (and titles,
+            # descriptions) *must* be unicode objects.  Good news is
+            # that the directive handler already made sure we either
+            # got pure ASCII or unicode here:
+            permission = unicode(permission)
+            # TODO permission title and description
+            component.provideUtility(Permission(permission, title=permission),
+                                     name=permission)
+
+        return True
+    
+class AnnotationGrokker(martian.ClassGrokker):
+    component_class = grok.Annotation
+ 
+    def grok(self, name, factory, context, module_info, templates):
+        adapter_context = util.determine_class_context(factory, context)
+        provides = util.class_annotation(factory, 'grok.provides', None)
+        if provides is None:
+            base_interfaces = interface.implementedBy(grok.Annotation)
+            factory_interfaces = interface.implementedBy(factory)
+            real_interfaces = list(factory_interfaces - base_interfaces)
+            util.check_implements_one_from_list(real_interfaces, factory)
+            provides = real_interfaces[0]
+
+        key = util.class_annotation(factory, 'grok.name', None)
+        if key is None:
+            key = factory.__module__ + '.' + factory.__name__
+
+        @component.adapter(adapter_context)
+        @interface.implementer(provides)
+        def getAnnotation(context):
+            annotations = IAnnotations(context)
+            try:
+                result = annotations[key]
+            except KeyError:
+                result = factory()
+                annotations[key] = result
+
+            # Containment has to be set up late to allow containment
+            # proxies to be applied, if needed. This does not trigger
+            # an event and is idempotent if containment is set up
+            # already.
+            contained_result = contained(result, context, key)
+            return contained_result
+
+        component.provideAdapter(getAnnotation)
+        return True
+
+class ApplicationGrokker(martian.ClassGrokker):
+    component_class = grok.Application
+    priority = 500
+
+    def grok(self, name, factory, context, module_info, templates):
+        # XXX fail loudly if the same application name is used twice.
+        zope.component.provideUtility(factory,
+                                      provides=grok.interfaces.IApplication,
+                                      name='%s.%s' % (module_info.dotted_name,
+                                                      name))
+        return True
+    
+class IndexesGrokker(martian.InstanceGrokker):
+    component_class = components.IndexesClass
+
+    def grok(self, name, factory, context, module_info, templates):
+        site = util.class_annotation(factory, 'grok.site', None)
+        if site is None:
+            raise GrokError("No site specified for grok.Indexes "
+                            "subclass in module %r. "
+                            "Use grok.site() to specify." % module_info.getModule(),
+                            factory)
+        indexes = util.class_annotation(factory, 'grok.indexes', None)
+        if indexes is None:
+            return False
+        context = util.determine_class_context(factory, context)
+        catalog_name = util.class_annotation(factory, 'grok.name', u'')
+        zope.component.provideHandler(
+            IndexesSetupSubscriber(catalog_name, indexes,
+                                   context, module_info),
+            adapts=(site,
+                    grok.IObjectAddedEvent))
+        return True
+    
+class IndexesSetupSubscriber(object):
+    def __init__(self, catalog_name, indexes, context, module_info):
+        self.catalog_name = catalog_name
+        self.indexes = indexes
+        self.context = context
+        self.module_info = module_info
+        
+    def __call__(self, site, event):
+        # make sure we have an intids
+        self._createIntIds(site)
+        # get the catalog
+        catalog = self._createCatalog(site)
+        # now install indexes
+        for name, index in self.indexes.items():
+            try:
+                index.setup(catalog, name, self.context, self.module_info)
+            except DuplicationError:
+                raise GrokError(
+                    "grok.Indexes in module %r causes "
+                    "creation of catalog index %r in catalog %r, "
+                    "but an index with that name is already present." %
+                    (self.module_info.getModule(), name, self.catalog_name),
+                    None)
+
+    def _createCatalog(self, site):
+        """Create the catalog if needed and return it.
+
+        If the catalog already exists, return that.
+        """
+        catalog = zope.component.queryUtility(
+            ICatalog, name=self.catalog_name, context=site, default=None)
+        if catalog is not None:
+            return catalog
+        catalog = Catalog()
+        setupUtility(site, catalog, ICatalog, name=self.catalog_name)
+        return catalog
+    
+    def _createIntIds(self, site):
+        """Create intids if needed, and return it.
+        """
+        intids = zope.component.queryUtility(
+            IIntIds, context=site, default=None)
+        if intids is not None:
+            return intids
+        intids = IntIds()
+        setupUtility(site, intids, IIntIds)
+        return intids
+
+class ILayerGrokker(martian.ClassGrokker):
+    component_class = grok.ILayer
+
+
+class SkinGrokker(martian.ClassGrokker):
+    component_class = grok.Skin
+
+    def grok(self, name, factory, context, module_info, templates):
+        layer = util.class_annotation(factory, 'grok.layer',
+                                    None) or module_info.getAnnotation('grok.layer',
+                                    None) or grok.IDefaultBrowserLayer
+        name = grok.util.class_annotation(factory, 'grok.name', factory.__name__.lower())
+        zope.component.interface.provideInterface(name, layer, IBrowserSkinType)
+
+        return True


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/meta.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/meta.zcml
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/meta.zcml	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/meta.zcml	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,13 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:meta="http://namespaces.zope.org/meta">
+
+  <meta:directives namespace="http://namespaces.zope.org/grok">
+    <meta:directive
+        name="grok"
+        schema=".zcml.IGrokDirective"
+        handler=".zcml.grokDirective"
+        />
+  </meta:directives>
+</configure>
+  
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/src/grok/publication.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/publication.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/publication.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,67 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Grok publication objects
+"""
+
+from zope.security.proxy import removeSecurityProxy
+from zope.security.checker import selectChecker
+
+from zope.app.publication.http import BaseHTTPPublication
+from zope.app.publication.browser import BrowserPublication
+from zope.app.publication.requestpublicationfactories import \
+     BrowserFactory, XMLRPCFactory
+
+
+class ZopePublicationSansProxy(object):
+
+    def getApplication(self, request):
+        result = super(ZopePublicationSansProxy, self).getApplication(request)
+        return removeSecurityProxy(result)
+
+    def traverseName(self, request, ob, name):
+        result = super(ZopePublicationSansProxy, self).traverseName(
+            request, ob, name)
+        return removeSecurityProxy(result)
+
+    def callObject(self, request, ob):
+        checker = selectChecker(ob)
+        if checker is not None:
+            checker.check(ob, '__call__')
+        return super(ZopePublicationSansProxy, self).callObject(request, ob)
+
+
+class GrokBrowserPublication(ZopePublicationSansProxy, BrowserPublication):
+
+    def getDefaultTraversal(self, request, ob):
+        obj, path = super(GrokBrowserPublication, self).getDefaultTraversal(
+            request, ob)
+        return removeSecurityProxy(obj), path
+
+
+class GrokBrowserFactory(BrowserFactory):
+
+    def __call__(self):
+        request, publication = super(GrokBrowserFactory, self).__call__()
+        return request, GrokBrowserPublication
+
+
+class GrokXMLRPCPublication(ZopePublicationSansProxy, BaseHTTPPublication):
+    pass
+
+
+class GrokXMLRPCFactory(XMLRPCFactory):
+
+    def __call__(self):
+        request, publication = super(GrokXMLRPCFactory, self).__call__()
+        return request, GrokXMLRPCPublication


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/publication.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/templatereg.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/templatereg.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/templatereg.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,58 @@
+from martian.error import GrokError
+
+import os
+import grok
+
+class TemplateRegistry(object):
+
+    def __init__(self):
+        self._reg = {}
+
+    def register(self, name, template):
+        self._reg[name] = dict(template=template, associated=False)
+
+    def markAssociated(self, name):
+        self._reg[name]['associated'] = True
+
+    def get(self, name):
+        entry = self._reg.get(name)
+        if entry is None:
+            return None
+        return entry['template']
+
+    def findFilesystem(self, module_info):
+        template_dir_name = module_info.getAnnotation(
+            'grok.templatedir', module_info.name + '_templates')
+
+        template_dir = module_info.getResourcePath(template_dir_name)
+
+        if not os.path.isdir(template_dir):
+            return
+        
+        for template_file in os.listdir(template_dir):
+            if template_file.startswith('.') or template_file.endswith('~'):
+                continue
+
+            if not template_file.endswith('.pt'):
+                raise GrokError("Unrecognized file '%s' in template directory "
+                                "'%s'." % (template_file, template_dir),
+                                module_info.getModule())
+
+            template_name = template_file[:-3] # cut off .pt
+            template = grok.PageTemplateFile(template_file, template_dir)
+            template_path = os.path.join(template_dir, template_file)
+            template._annotateGrokInfo(template_name, template_path)
+
+            inline_template = self.get(template_name)
+            if inline_template:
+                raise GrokError("Conflicting templates found for name '%s' "
+                                "in module %r, both inline and in template "
+                                "directory '%s'."
+                                % (template_name, module_info.getModule(),
+                                   template_dir), inline_template)
+            self.register(template_name, template)
+
+    def listUnassociated(self):
+        for name, entry in self._reg.iteritems():
+            if not entry['associated']:
+                yield name


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/templatereg.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/templates/default_display_form.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/templates/default_display_form.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/templates/default_display_form.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,36 @@
+<html>
+<head>
+</head>
+
+<body>
+  <table class="listing">
+    <thead>
+      <tr>
+        <th class="label-column">&nbsp;</th>
+        <th>&nbsp;</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tal:block repeat="widget view/widgets">
+        <tr tal:define="odd repeat/widget/odd"
+          tal:attributes="class python: odd and 'odd' or 'even'">
+          <td class="fieldname">
+            <tal:block content="widget/label"/>
+          </td>
+          <td>
+            <input tal:replace="structure widget" />
+          </td>
+        </tr>
+      </tal:block>
+    </tbody>
+    <tfoot>
+      <tr class="controls">
+        <td colspan="2" class="align-right">
+          <input tal:repeat="action view/actions" 
+            tal:replace="structure action/render" />
+        </td>
+      </tr>
+    </tfoot>
+  </table>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/src/grok/templates/default_edit_form.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/templates/default_edit_form.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/templates/default_edit_form.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,69 @@
+<html>
+<head>
+</head>
+
+<body>
+<form action="." tal:attributes="action request/URL" method="post"
+      class="edit-form" enctype="multipart/form-data">
+
+  <h1 i18n:translate=""
+    tal:condition="view/label"
+    tal:content="view/label">Label</h1>
+
+  <div class="form-status"
+    tal:define="status view/status"
+    tal:condition="status">
+
+    <div i18n:translate="" tal:content="view/status">
+      Form status summary
+    </div>
+
+    <ul class="errors" tal:condition="view/errors">
+      <li tal:repeat="error view/error_views">
+         <span tal:replace="structure error">Error Type</span>
+      </li>
+    </ul>
+  </div>
+
+  <table class="form-fields">
+    <tbody>
+      <tal:block repeat="widget view/widgets">
+        <tr>
+          <td class="label" tal:define="hint widget/hint">
+            <label tal:condition="python:hint"
+                   tal:attributes="for widget/name">
+              <span class="required" tal:condition="widget/required"
+              >*</span><span i18n:translate=""
+                             tal:content="widget/label">label</span>
+            </label>
+            <label tal:condition="python:not hint"
+                   tal:attributes="for widget/name">
+              <span class="required" tal:condition="widget/required"
+              >*</span><span i18n:translate=""
+                             tal:content="widget/label">label</span>
+            </label>
+          </td>
+          <td class="field">
+            <div class="widget" tal:content="structure widget">
+              <input type="text" />
+            </div>
+            <div class="error" tal:condition="widget/error">
+              <span tal:replace="structure widget/error">error</span>
+            </div>
+          </td>
+        </tr>
+      </tal:block>
+    </tbody>
+  </table>
+
+  <div id="actionsView">
+    <span class="actionButtons" tal:condition="view/availableActions">
+      <input tal:repeat="action view/actions"
+             tal:replace="structure action/render"
+             />
+    </span>
+  </div>
+</form>
+
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/adapter.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/adapter.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/adapter.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,36 @@
+"""
+  >>> grok.grok(__name__)
+
+  >>> cave = Cave()
+  >>> home = IHome(cave)
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+
+  >>> fireplace = IFireplace(cave)
+  >>> IFireplace.providedBy(fireplace)
+  True
+  >>> isinstance(fireplace, Fireplace)
+  True
+"""
+
+import grok
+from zope import interface
+
+class Cave(grok.Model):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)
+
+class IFireplace(interface.Interface):
+    pass
+
+class Fireplace(grok.Adapter):
+    grok.implements(IFireplace, IHome)
+    grok.provides(IFireplace)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/adapter.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/alphabetical.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/alphabetical.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/alphabetical.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,26 @@
+"""
+Grok does not depend on the alphabetical order:
+
+  >>> grok.grok(__name__)
+
+  >>> cave = ZCave()
+  >>> home = IHome(cave)
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+
+"""
+import grok
+from zope import interface
+
+class ZCave(grok.Model):
+    """we call this `ZCave` because we want to test that we do not
+    depend on alphabetical order"""
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/alphabetical.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontext.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontext.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontext.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,29 @@
+"""
+Explicit class-level context in case of multiple models:
+
+  >>> grok.grok(__name__)
+
+  >>> cave = Cave()
+  >>> home = IHome(cave)
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+
+"""
+import grok
+from zope import interface
+
+class Cave(grok.Model):
+    pass
+
+class Club(grok.Model):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)
+    grok.context(Cave)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontext.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextimported.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextimported.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextimported.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,24 @@
+"""
+Explicit class-level context for an imported model:
+
+  >>> grok.grok(__name__)
+
+  >>> cave = Cave()
+  >>> painting = IPainting(cave)
+
+  >>> IPainting.providedBy(painting)
+  True
+  >>> isinstance(painting, Painting)
+  True
+
+"""
+import grok
+from grok.tests.adapter.adapter import Cave
+from zope import interface
+
+class IPainting(interface.Interface):
+    pass
+
+class Painting(grok.Adapter):
+    grok.implements(IPainting)
+    grok.context(Cave)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextimported.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextmultiple.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextmultiple.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextmultiple.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,10 @@
+"""
+You can't call grok.context multiple times on class level:
+
+  >>> import grok.tests.adapter.classcontextmultiple_fixture
+  Traceback (most recent call last):
+    ...
+  GrokImportError: grok.context can only be called once per class or module.
+
+"""
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextmultiple.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextmultiple_fixture.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextmultiple_fixture.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextmultiple_fixture.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,11 @@
+import grok
+
+class Cave(grok.Model):
+    pass
+
+class Club(grok.Model):
+    pass
+
+class Anything(object):
+    grok.context(Cave)
+    grok.context(Club)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classcontextmultiple_fixture.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classorinterface.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classorinterface.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classorinterface.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,46 @@
+"""
+You can only use `grok.context` with interfaces or classes and not
+with anything else:
+
+  >>> function_context()
+  Traceback (most recent call last):
+    ...
+  GrokImportError: You can only pass classes or interfaces to grok.context.
+
+  >>> string_context()
+  Traceback (most recent call last):
+    ...
+  GrokImportError: You can only pass classes or interfaces to grok.context.
+
+  >>> module_context()
+  Traceback (most recent call last):
+    ...
+  GrokImportError: You can only pass classes or interfaces to grok.context.
+
+  >>> instance_context()
+  Traceback (most recent call last):
+    ...
+  GrokImportError: You can only pass classes or interfaces to grok.context.
+
+"""
+import grok
+
+def function_context():
+    def a():
+        pass
+
+    class FunctionContext(object):
+        grok.context(a)
+
+def string_context():
+    class StringContext(object):
+        grok.context('string')
+
+def module_context():
+    class ModuleContext(object):
+        grok.context(grok)
+
+def instance_context():
+    obj = object()
+    class InstanceContext(object):
+        grok.context(obj)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/classorinterface.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/functioncontext.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/functioncontext.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/functioncontext.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,30 @@
+"""
+You can't call grok.context from a function:
+
+  >>> func()
+  Traceback (most recent call last):
+    ...
+  GrokImportError: grok.context can only be used on class or module level.
+
+You can't call grok.context from a method either:
+
+  >>> SomeClass().meth()
+  Traceback (most recent call last):
+    ...
+  GrokImportError: grok.context can only be used on class or module level.
+
+"""
+import grok
+from grok.tests.adapter.adapter import Cave
+
+def func():
+    """We don't allow calling `grok.context` from anything else than a
+    module or a class"""
+    grok.context(Cave)
+
+class SomeClass(object):
+
+    def meth(self):
+        """We don't allow calling `grok.context` from anything else
+        than a module or a class"""
+        grok.context(Cave)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/functioncontext.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsmany.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsmany.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsmany.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,25 @@
+"""
+Subclasses of grok.Adapter and grok.MultiAdapter must implement exactly one
+interface:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: <class 'grok.tests.adapter.implementsmany.Home'> is implementing
+  more than one interface (use grok.provides to specify which one to use).
+"""
+import grok
+
+from zope import interface
+
+class Cave(grok.Model):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class IFireplace(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome, IFireplace)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsmany.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsnone.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsnone.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsnone.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,17 @@
+"""
+Subclasses of grok.Adapter and grok.MultiAdapter must implement exactly one
+interface:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: <class 'grok.tests.adapter.implementsnone.Home'> must
+  implement at least one interface (use grok.implements to specify).
+"""
+import grok
+
+class Cave(grok.Model):
+    pass
+
+class Home(grok.Adapter):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsnone.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsnonemulti.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsnonemulti.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsnonemulti.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,17 @@
+"""
+Subclasses of grok.Adapter and grok.MultiAdapter must implement exactly one
+interface:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: <class 'grok.tests.adapter.implementsnonemulti.Home'> must
+  implement at least one interface (use grok.implements to specify).
+"""
+import grok
+
+class Cave(grok.Model):
+    pass
+
+class Home(grok.MultiAdapter):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/implementsnonemulti.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/importedmodel.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/importedmodel.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/importedmodel.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,14 @@
+"""
+Imported model and adapter won't be grokked:
+
+  >>> import grok
+  >>> grok.grok(__name__)
+  >>> from grok.tests.adapter.adapter import IHome
+  >>> cave = Cave()
+  >>> home = IHome(cave)
+  Traceback (most recent call last):
+    ...
+  TypeError: ('Could not adapt', <grok.tests.adapter.adapter.Cave object at ...>, <InterfaceClass grok.tests.adapter.adapter.IHome>)
+
+"""
+from grok.tests.adapter.adapter import Cave, Home


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/importedmodel.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/importedmodel2.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/importedmodel2.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/importedmodel2.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,23 @@
+"""
+Grok error because import model doesn't count as context:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: No module-level context for
+  <class 'grok.tests.adapter.importedmodel2.Painting'>, please use grok.context.
+
+"""
+import grok
+from grok.tests.adapter.adapter import Cave
+from zope import interface
+
+class IPainting(interface.Interface):
+    pass
+
+class Painting(grok.Adapter):
+    """
+    Grokking of this should fail because there's no model (only an
+    imported one which doesn't count).
+    """
+    grok.implements(IPainting)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/importedmodel2.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/interface.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/interface.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/interface.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,41 @@
+"""
+You can also specify interfaces instead of classes with
+`grok.context` (class-level):
+
+  >>> grok.grok(__name__)
+
+  >>> cave = Cave()
+  >>> home = IHome(cave)
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+
+  >>> hole = Hole()
+  >>> home = IHome(hole)
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+
+"""
+import grok
+from zope import interface
+
+class ICave(interface.Interface):
+    pass
+
+class Cave(grok.Model):
+    grok.implements(ICave)
+
+class Hole(grok.Model):
+    grok.implements(ICave)
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)
+    grok.context(ICave)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/interface.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/interfacemodule.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/interfacemodule.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/interfacemodule.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,42 @@
+"""
+You can also specify interfaces instead of classes with
+`grok.context` (module-level):
+
+  >>> grok.grok(__name__)
+
+  >>> cave = Cave()
+  >>> home = IHome(cave)
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+
+  >>> hole = Hole()
+  >>> home = IHome(hole)
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+
+"""
+import grok
+from zope import interface
+
+class ICave(interface.Interface):
+    pass
+
+class Cave(grok.Model):
+    grok.implements(ICave)
+
+class Hole(grok.Model):
+    grok.implements(ICave)
+
+grok.context(ICave)
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/interfacemodule.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontext.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontext.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontext.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,30 @@
+"""
+Explicit module-level context in case of multiple models:
+
+  >>> grok.grok(__name__)
+
+  >>> cave = Cave()
+  >>> home = IHome(cave)
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+
+"""
+import grok
+from zope import interface
+
+class Cave(grok.Model):
+    pass
+
+class Club(grok.Model):
+    pass
+
+grok.context(Cave)
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontext.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextimported.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextimported.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextimported.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,25 @@
+"""
+Explicit module-level context for an imported model:
+
+  >>> grok.grok(__name__)
+
+  >>> cave = Cave()
+  >>> painting = IPainting(cave)
+
+  >>> IPainting.providedBy(painting)
+  True
+  >>> isinstance(painting, Painting)
+  True
+
+"""
+import grok
+from grok.tests.adapter.adapter import Cave
+from zope import interface
+
+grok.context(Cave)
+
+class IPainting(interface.Interface):
+    pass
+
+class Painting(grok.Adapter):
+    grok.implements(IPainting)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextimported.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextmultiple.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextmultiple.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextmultiple.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+"""
+You can't call grok.context multiple times on module level:
+
+  >>> import grok.tests.adapter.modulecontextmultiple_fixture
+  Traceback (most recent call last):
+    ...
+  GrokImportError: grok.context can only be called once per class or module.
+
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextmultiple.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextmultiple_fixture.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextmultiple_fixture.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextmultiple_fixture.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,11 @@
+import grok
+from zope import interface
+
+class Cave(grok.Model):
+    pass
+
+class Club(grok.Model):
+    pass
+
+grok.context(Cave)
+grok.context(Club)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/modulecontextmultiple_fixture.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiadapter.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiadapter.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiadapter.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,91 @@
+"""
+Multi-Adapters are supported by subclassing grok.MultiAdapter, giving
+multiple arguments to grok.adapts, and supplying a matching
+__init__():
+
+  >>> grok.grok(__name__)
+
+  >>> cave = Cave()
+  >>> fireplace = Fireplace()
+
+  >>> from zope import component
+  >>> home = component.getMultiAdapter((cave, fireplace))
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+  >>> home.cave is cave
+  True
+  >>> home.fireplace is fireplace
+  True
+
+This also works for named adapters using grok.name:
+
+  >>> home = component.getMultiAdapter((cave, fireplace), name='home2')
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home2)
+  True
+  >>> home.cave is cave
+  True
+  >>> home.fireplace is fireplace
+  True
+
+Multiadapters that implement more than one interface can use grok.provides to
+specify the one to use:
+
+  >>> home = component.getMultiAdapter((cave, fireplace), name='home3')
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home3)
+  True
+  >>> home.cave is cave
+  True
+  >>> home.fireplace is fireplace
+  True
+"""
+
+import grok
+from zope import interface
+
+class Cave(grok.Model):
+    pass
+
+class Fireplace(grok.Model):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.MultiAdapter):
+    grok.adapts(Cave, Fireplace)
+    grok.implements(IHome)
+
+    def __init__(self, cave, fireplace):
+        self.cave = cave
+        self.fireplace = fireplace
+
+class Home2(grok.MultiAdapter):
+    grok.adapts(Cave, Fireplace)
+    grok.implements(IHome)
+    grok.name('home2')
+
+    def __init__(self, cave, fireplace):
+        self.cave = cave
+        self.fireplace = fireplace
+
+class IFireplace(interface.Interface):
+    pass
+
+class Home3(grok.MultiAdapter):
+    grok.adapts(Cave, Fireplace)
+    grok.implements(IHome, IFireplace)
+    grok.provides(IHome)
+    grok.name('home3')
+
+    def __init__(self, cave, fireplace):
+        self.cave = cave
+        self.fireplace = fireplace


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiadapter.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiadaptsnone.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiadaptsnone.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiadaptsnone.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,18 @@
+"""
+Subclasses of grok.MultiAdapter must declare what they adapt, using grok.adapts:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: <class 'grok.tests.adapter.multiadaptsnone.Home'> must specify
+  which contexts it adapts (use grok.adapts to specify).
+"""
+import grok
+
+from zope import interface
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.MultiAdapter):
+    grok.implements(IHome)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiadaptsnone.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiple.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiple.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiple.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,24 @@
+"""
+Multiple models lead to ambiguity:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: Multiple possible contexts for
+  <class 'grok.tests.adapter.multiple.Home'>, please use grok.context.
+
+"""
+import grok
+from zope import interface
+
+class Cave(grok.Model):
+    pass
+
+class Club(grok.Model):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/multiple.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/namedadapter.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/namedadapter.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/namedadapter.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,31 @@
+"""
+You can register a named adapter by using grok.name:
+
+  >>> grok.grok(__name__)
+
+  >>> cave = Cave()
+  >>> home = IHome(cave)
+  Traceback (most recent call last):
+    ...
+  TypeError: ('Could not adapt', <grok.tests.adapter.namedadapter.Cave object at 0x...>, <InterfaceClass grok.tests.adapter.namedadapter.IHome>)
+
+  >>> from zope.component import getAdapter
+  >>> home = getAdapter(cave, IHome, name='home')
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+"""
+
+import grok
+from zope import interface
+
+class Cave(grok.Model):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)
+    grok.name('home')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/namedadapter.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/nomodel.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/nomodel.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/nomodel.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,18 @@
+"""
+If no model can be found in the module, we get an error:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: No module-level context for
+  <class 'grok.tests.adapter.nomodel.Home'>, please use grok.context.
+
+"""
+import grok
+from zope import interface
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/nomodel.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/oldstyleclass.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/oldstyleclass.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/oldstyleclass.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,25 @@
+"""
+Old-style classes are also supported:
+
+  >>> grok.grok(__name__)
+
+  >>> cave = Cave()
+  >>> home = IHome(cave)
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+"""
+import grok
+from zope import interface
+
+class Cave:
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)
+    grok.context(Cave)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/oldstyleclass.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/order.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/order.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/order.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,26 @@
+"""
+If the model is defined after the adapter, it should still be grokked
+properly:
+
+  >>> grok.grok(__name__)
+
+  >>> cave = Cave()
+  >>> home = IHome(cave)
+
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+
+"""
+import grok
+from zope import interface
+
+class IHome(interface.Interface):
+    pass
+
+class Home(grok.Adapter):
+    grok.implements(IHome)
+
+class Cave(grok.Model):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/adapter/order.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/annotation.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/annotation.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/annotation.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,49 @@
+"""
+  >>> grok.grok(__name__)
+  >>> from zope import component
+  >>> from zope.annotation.attribute import AttributeAnnotations
+  >>> component.provideAdapter(AttributeAnnotations)
+
+We can adapt a model to an annotation interface and obtain a
+persistent annotation storage:
+
+  >>> manfred = Mammoth()
+  >>> branding = IBranding(manfred)
+  >>> branding.addBrand('mine')
+  >>> branding.addBrand('yours')
+
+Regetting the adapter will yield the same annotation storage:
+
+  >>> brands = IBranding(manfred).getBrands()
+  >>> brands.sort()
+  >>> brands
+  ['mine', 'yours']
+
+"""
+
+import grok
+from zope import interface
+from BTrees.OOBTree import OOTreeSet
+
+class Mammoth(grok.Model):
+    pass
+
+class IBranding(interface.Interface):
+
+    def addBrand(brand):
+        """Brand an animal with ``brand``, a string."""
+
+    def getBrands():
+        """Return a list of brands."""
+
+class Branding(grok.Annotation):
+    grok.implements(IBranding)
+
+    def __init__(self): 
+        self._brands = OOTreeSet()
+
+    def addBrand(self, brand):
+        self._brands.insert(brand)
+
+    def getBrands(self):
+        return list(self._brands)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/annotation.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/implementsmany.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/implementsmany.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/implementsmany.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,27 @@
+"""
+An annotations class must implement either exactly one interface, or
+it should cspecify which of the many implemented interfaces it should
+be registered for.  Ambiguities lead to errors:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  GrokError: <class
+  'grok.tests.annotation.implementsmany.MammothAnnotations'> is
+  implementing more than one interface (use grok.provides to specify
+  which one to use).
+"""
+
+import grok
+from zope import interface
+
+class Mammoth(grok.Model):
+    pass
+
+class IOneInterface(interface.Interface):
+    pass
+
+class IAnotherInterface(interface.Interface):
+    pass
+
+class MammothAnnotations(grok.Annotation):
+    grok.implements(IOneInterface, IAnotherInterface)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/implementsmany.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/implementsnone.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/implementsnone.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/implementsnone.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+"""
+Subclasses of grok.Annotation must implement at least one additional
+interface to indicate which annotation interface they provide and can
+be looked up with:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  GrokError: <class 'grok.tests.annotation.implementsnone.Branding'>
+  must implement at least one interface (use grok.implements to
+  specify).
+
+"""
+
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class Branding(grok.Annotation):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/implementsnone.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/name.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/name.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/name.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,49 @@
+"""
+  >>> grok.grok(__name__)
+  >>> from zope import component
+  >>> from zope.annotation.attribute import AttributeAnnotations
+  >>> component.provideAdapter(AttributeAnnotations)
+
+If an annotation class doesn't specify anything else, its dotted name
+will be used as an annotation key:
+
+  >>> manfred = Mammoth()
+  >>> ann = IImplicitName(manfred)
+
+  >>> from zope.annotation.interfaces import IAnnotations
+  >>> 'grok.tests.annotation.name.ImplicitName' in IAnnotations(manfred)
+  True
+
+Of course, annotation classes can explicity specify the name of the
+annotation key that they will be stored under.  That's useful if you
+want a meaningful key that's accessible from other applications and if
+you want to be able to move the class around during refactorings (then
+the dotted name will obviously change)
+
+  >>> ann = IExplicitName(manfred)
+  >>> 'grok.tests.annotation.name.ExplicitName' in IAnnotations(manfred)
+  False
+  >>> 'mammoth.branding' in IAnnotations(manfred)
+  True
+
+"""
+
+import grok
+from zope import interface
+from BTrees.OOBTree import OOTreeSet
+
+class Mammoth(grok.Model):
+    pass
+
+class IExplicitName(interface.Interface):
+    pass
+
+class IImplicitName(interface.Interface):
+    pass
+
+class ExplicitName(grok.Annotation):
+    grok.implements(IExplicitName)
+    grok.name('mammoth.branding')
+
+class ImplicitName(grok.Annotation):
+    grok.implements(IImplicitName)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/name.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/provides.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/provides.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/provides.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,37 @@
+"""
+  >>> grok.grok(__name__)
+  >>> from zope import component
+  >>> from zope.annotation.attribute import AttributeAnnotations
+  >>> component.provideAdapter(AttributeAnnotations)
+
+If an annotation class implements more than one interface, it has to
+declare which one it should be registered for using ``grok.provides``.
+
+  >>> manfred = Mammoth()
+  >>> ann = IOneInterface(manfred)
+
+It can then be looked up only using that one interface:
+
+  >>> IAnotherOne(manfred)
+  Traceback (most recent call last):
+  TypeError: ('Could not adapt', <grok.tests.annotation.provides.Mammoth object at ...>, <InterfaceClass grok.tests.annotation.provides.IAnotherOne>)
+
+
+"""
+
+import grok
+from zope import interface
+from BTrees.OOBTree import OOTreeSet
+
+class Mammoth(grok.Model):
+    pass
+
+class IOneInterface(interface.Interface):
+    pass
+
+class IAnotherOne(interface.Interface):
+    pass
+
+class MammothAnnotation(grok.Annotation):
+    grok.implements(IOneInterface, IAnotherOne)
+    grok.provides(IOneInterface)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/annotation/provides.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/application/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/application/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/application/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/application/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/application/application.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/application/application.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/application/application.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,33 @@
+"""
+
+After grokking a module that defines an application, the application factory is
+available as a utility::
+
+    >>> grok.grok(__name__)
+    >>> import zope.component
+    >>> import grok.interfaces
+    >>> calendar_app = zope.component.getUtility(grok.interfaces.IApplication,
+    ...                                          name='grok.tests.application.application.Calendar')
+    >>> calendar_app
+    <class 'grok.tests.application.application.Calendar'>
+
+Applications are both containers and sites::
+
+    >>> issubclass(calendar_app, grok.Site)
+    True
+
+Applications can be instanciated without any arguments::
+
+    >>> calendar = calendar_app()
+    >>> calendar
+    <grok.tests.application.application.Calendar object at 0x...>
+
+"""
+
+import grok
+
+
+class Calendar(grok.Application):
+    """A calendar application that knows about ancient
+    calendar systems from the stone age.
+    """


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/application/application.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+#


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/base.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/base.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/base.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,44 @@
+"""
+Base classes shouldn't be grokked.
+
+One way to indicate that something is a base class is by postfixing the
+classname with 'Base'. Another way is to use the 'grok.baseclass' directive
+on the class itself.
+
+  >>> grok.grok(__name__)
+
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+  >>> model = ModelBase()
+  >>> view = component.getMultiAdapter((model, request), name='viewbase')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: ((<grok.tests.baseclass.base.ModelBase object at 0x...>,
+  <zope.publisher.browser.TestRequest instance ...>),
+  <InterfaceClass zope.interface.Interface>,
+  'viewbase')
+
+  >>> view = component.getMultiAdapter((model, request), name='anotherview')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: ((<grok.tests.baseclass.base.ModelBase object at 0x...>,
+  <zope.publisher.browser.TestRequest instance ...>),
+  <InterfaceClass zope.interface.Interface>,
+  'anotherview')
+  
+"""
+import grok
+
+class ModelBase(grok.Model):
+    pass
+
+class ViewBase(grok.View):
+    def render(self):
+        return "hello world"
+
+class AnotherView(grok.View):
+    grok.baseclass()
+    
+    def render(self):
+        return "hello world"


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/base.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/basecontext.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/basecontext.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/basecontext.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,34 @@
+"""
+A base class of something that can be a context (such as a model) can
+function as a module-level context, and thus can have views associated
+with it.
+
+  >>> grok.grok(__name__)
+
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+  >>> model = ModelBase()
+  >>> view = component.getMultiAdapter((model, request), name='viewbase')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: ((<grok.tests.baseclass.basecontext.ModelBase object at 0x...>,
+  <zope.publisher.browser.TestRequest instance ...>),
+  <InterfaceClass zope.interface.Interface>,
+  'viewbase')
+  >>> view = component.getMultiAdapter((model, request), name='realview')
+  >>> view.render()
+  'hello world'
+"""
+
+import grok
+
+class ModelBase(grok.Model):
+    pass
+
+class ViewBase(grok.View):    
+    def render(self):
+        return "hello world"
+
+class RealView(ViewBase):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/basecontext.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/basedirective.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/basedirective.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/basedirective.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,42 @@
+"""
+The baseclass directive can be used to mark something a base class. Of course
+subclasses shouldn't inherit this otherwise there is no way to turn them
+into non-base classes.
+
+  >>> grok.grok(__name__)
+
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+  >>> model = Model()
+
+We can't look up SomeView as a view, as it's a base class:
+
+  >>> view = component.getMultiAdapter((model, request), name='someview')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: ((<grok.tests.baseclass.basedirective.Model object at 0x...>,
+  <zope.publisher.browser.TestRequest instance ...>),
+  <InterfaceClass zope.interface.Interface>,
+  'someview')
+
+We can however get a subclass of SomeView:
+
+  >>> view = component.getMultiAdapter((model, request), name='anotherview')
+  >>> view.render()
+  'hello world'
+"""
+import grok
+
+class Model(grok.Model):
+    pass
+
+class SomeView(grok.View):
+    grok.baseclass()
+    
+    def render(self):
+        return "hello world"
+
+class AnotherView(SomeView):
+    pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/baseclass/basedirective.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/container/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/container/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/container/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/container/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/container/container.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/container/container.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/container/container.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,40 @@
+"""
+
+The grok.Container is a a model that is also a container.  It has a
+dictionary API. It in fact stores its information in a BTree so
+you can store a lot of items in a scalable way.
+
+    >>> grok.grok(__name__)
+
+    >>> from zope.app.container.interfaces import IContainer
+    >>> bag = BoneBag()
+    >>> IContainer.providedBy(bag)
+    True
+
+    >>> from zope.app.container.btree import BTreeContainer
+    >>> isinstance(bag, BTreeContainer)
+    True
+     
+We had problems when switching to grok.Container with the __parent__ attribute
+being set, we better make sure this doesn't happen again:
+
+    >>> skull = Bone()
+    >>> print skull.__parent__
+    None
+    >>> print skull.__name__
+    None
+    >>> bag['skull'] = skull
+    >>> skull.__parent__
+    <grok.tests.container.container.BoneBag object at 0x...>
+    >>> skull.__name__
+    u'skull'
+
+"""
+
+import grok
+
+class BoneBag(grok.Container):
+    pass
+    
+class Bone(grok.Model):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/container/container.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/container/container_model.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/container/container_model.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/container/container_model.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,24 @@
+"""
+We make sure we indeed have a view for BoneBag; this way we know it's
+registered as the default context object:
+
+
+    >>> grok.grok(__name__)
+    >>> bag = BoneBag()
+    >>> from zope import component
+    >>> from zope.publisher.browser import TestRequest
+    >>> request = TestRequest()
+    >>> view = component.getMultiAdapter((bag, request), name='index')
+    >>> view()
+    'Hello world'
+"""
+import grok
+
+class BoneBag(grok.Container):
+    pass
+
+class Index(grok.View):
+    """A simple view to test whether BoneBag is really registered as a model.
+    """
+    def render(self):
+        return "Hello world"


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/container/container_model.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/argumenterror.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/argumenterror.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/argumenterror.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,6 @@
+"""
+   >>> import grok.tests.directive.argumenterror_fixture
+   Traceback (most recent call last):
+     ...
+   TypeError: grok.templatedir takes exactly 1 argument (3 given)
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/argumenterror.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/argumenterror_fixture.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/argumenterror_fixture.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/argumenterror_fixture.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+import grok
+
+grok.templatedir('too', 'many', 'arguments')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/argumenterror_fixture.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/multipletimes.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/multipletimes.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/multipletimes.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,42 @@
+"""
+Since grok.global_utility is a MultipleTimesDirective, there is a list of
+GlobalUtilityInfo objects annotated on the module.
+
+  >>> from martian import scan
+  >>> from grok.tests.directive import multipletimes
+  >>> module_info = scan.module_info_from_module(multipletimes)
+  >>> guis = module_info.getAnnotation('grok.global_utility', None)
+  >>> guis
+  [<grok.directive.GlobalUtilityInfo object at 0x...>,
+  <grok.directive.GlobalUtilityInfo object at 0x...>]
+  >>> guis[0].factory
+  <class 'grok.tests.directive.multipletimes.Club'>
+  >>> guis[0].provides
+  <InterfaceClass grok.tests.directive.multipletimes.IClub>
+  >>> guis[0].name
+  'foo'
+  >>> guis[1].factory
+  <class 'grok.tests.directive.multipletimes.Cave'>
+  >>> guis[1].provides is None
+  True
+  >>> guis[1].name
+  u''
+  
+"""
+import grok
+from zope import interface
+
+class IClub(interface.Interface):
+    pass
+
+class ICave(interface.Interface):
+    pass
+
+class Club(object):
+    grok.implements(IClub)
+
+class Cave(object):
+    grok.implements(ICave)
+
+grok.global_utility(Club, provides=IClub, name='foo')
+grok.global_utility(Cave)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/directive/multipletimes.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/error/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/error/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/error/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/error/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/error/error.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/error/error.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/error/error.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,23 @@
+"""
+
+We expect this grok to fail, and give 
+
+  >>> try:
+  ...     grok.grok(__name__)
+  ... except grok.GrokError, error:
+  ...     pass
+  >>> error.component
+  <class 'grok.tests.error.error.CavePainting'>
+
+"""
+
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class CavePainting(grok.View):
+    grok.template("a")
+
+a = grok.PageTemplate("a")
+cavepainting = grok.PageTemplate("b")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/error/error.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/event/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/event/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/event/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/event/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/event/errorconditions.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/event/errorconditions.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/event/errorconditions.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,34 @@
+"""
+ at grok.subscribe can only be used on module level:
+
+  >>> function_context()
+  Traceback (most recent call last):
+    ...
+  GrokImportError: @grok.subscribe can only be used on module level.
+  
+  >>> class_context()
+  Traceback (most recent call last):
+    ...
+  GrokImportError: @grok.subscribe can only be used on module level.
+
+
+ at grok.subscribe can not be called without arguments:
+
+  >>> import grok.tests.event.errorconditions_fixture
+  Traceback (most recent call last):
+    ...
+  GrokImportError: @grok.subscribe requires at least one argument.
+  
+"""
+import grok
+
+def function_context():
+    @grok.subscribe(grok.Model, grok.IObjectCreatedEvent)
+    def subscriber():
+        pass
+    
+def class_context():
+    class Wrapper:
+        @grok.subscribe(grok.Model, grok.IObjectCreatedEvent)
+        def subscriber(self):
+            pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/event/errorconditions.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/event/errorconditions_fixture.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/event/errorconditions_fixture.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/event/errorconditions_fixture.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+import grok
+
+ at grok.subscribe()
+def subscriber():
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/event/errorconditions_fixture.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/event/subscriber.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/event/subscriber.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/event/subscriber.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+"""
+You can subscribe to events using the @grok.subscribe decorator:
+
+  >>> grok.grok(__name__)
+  >>> manfred = Mammoth('Manfred')
+  >>> grok.notify(grok.ObjectCreatedEvent(manfred))
+  >>> mammoths
+  ['Manfred']
+  >>> mammoths2
+  ['Manfred']
+
+"""
+import grok
+
+class Mammoth(object):
+    def __init__(self, name):
+        self.name = name
+
+mammoths = []
+mammoths2 = []
+
+ at grok.subscribe(Mammoth, grok.IObjectCreatedEvent)
+def mammothAdded(mammoth, event):
+    mammoths.append(mammoth.name)
+
+ at grok.subscribe(Mammoth, grok.ObjectCreatedEvent)
+def mammothAddedInstance(mammoth, event):
+    mammoths2.append(mammoth.name)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/event/subscriber.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/form/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/form/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/customautoform.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/form/customautoform.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/form/customautoform.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,50 @@
+"""
+A form view can have a custom form_fields but reusing those fields that
+were deduced automatically, using grok.AutoFields:
+
+  >>> grok.grok(__name__)
+
+We only expect a single field to be present in the form, as we omitted 'size':
+
+  >>> from zope import component
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> view = component.getMultiAdapter((Mammoth(), request), name='edit')
+  >>> len(view.form_fields)
+  1
+  >>> [w.__name__ for w in view.form_fields]
+  ['name']
+
+  >>> view = component.getMultiAdapter((Mammoth2(), request), name='edit2')
+  >>> len(view.form_fields)
+  1
+  >>> [w.__name__ for w in view.form_fields]
+  ['size']
+  
+"""
+
+import grok
+from zope import interface, schema
+
+class IMammoth(interface.Interface):
+    name = schema.TextLine(title=u"Name")
+    size = schema.TextLine(title=u"Size", default=u"Quite normal")
+
+class Mammoth(grok.Model):
+    interface.implements(IMammoth)
+
+class Edit(grok.EditForm):
+    grok.context(Mammoth)
+
+    form_fields = grok.AutoFields(Mammoth).omit('size')
+
+class Mammoth2(grok.Model):
+    class fields:
+        name = schema.TextLine(title=u"Name")
+        size = schema.TextLine(title=u"Size", default=u"Quite normal")
+
+class Edit2(grok.EditForm):
+    grok.context(Mammoth2)
+
+    form_fields = grok.AutoFields(Mammoth).omit('name')
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/customautoform.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/customform.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/form/customform.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/form/customform.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,33 @@
+"""
+A form view can completely override which fields are displayed by setting
+form_fields manually:
+
+  >>> grok.grok(__name__)
+
+We only expect a single field to be present in the form, as we omitted 'size':
+
+  >>> from zope import component
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> view = component.getMultiAdapter((Mammoth(), request), name='edit')
+  >>> len(view.form_fields)
+  1
+  >>> [w.__name__ for w in view.form_fields]
+  ['name']
+
+"""
+
+import grok
+from zope import interface, schema
+
+class IMammoth(interface.Interface):
+    name = schema.TextLine(title=u"Name")
+    size = schema.TextLine(title=u"Size", default=u"Quite normal")
+
+class Mammoth(grok.Model):
+    interface.implements(IMammoth)
+
+class Edit(grok.EditForm):
+    grok.context(Mammoth)
+
+    form_fields = grok.Fields(IMammoth).omit('size')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/customform.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/fields.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/form/fields.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/form/fields.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,29 @@
+"""
+A grok.Fields can receive keyword parameters with schema fields. These
+should be avaible in the definition order.
+
+  >>> grok.grok(__name__)
+
+  >>> from zope import component
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> view = component.getMultiAdapter((Mammoth(), request), name='edit')
+  >>> len(view.form_fields)
+  4
+  >>> [w.__name__ for w in view.form_fields]
+  ['a', 'b', 'g', 'd']
+
+"""
+import grok
+from zope import schema
+
+class Mammoth(grok.Model):
+    pass
+
+class Edit(grok.EditForm):
+    form_fields = grok.Fields(
+        a = schema.TextLine(title=u"Alpha"),
+        b = schema.TextLine(title=u"Beta"),
+        g = schema.TextLine(title=u"Gamma"),
+        d = schema.TextLine(title=u"Delta"))
+    


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/fields.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/form.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/form/form.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/form/form.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,69 @@
+"""
+A grok.Model may contain a nested class named 'fields'. All attributes of
+'fields' that provide IField will cause attributes of the same name to appear on
+the grok.Model:
+
+  >>> grok.grok(__name__)
+  >>> manfred = Mammoth()
+  >>> print manfred.name
+  None
+  >>> print manfred.size
+  Quite normal
+  >>> manfred.somethingelse
+  Traceback (most recent call last):
+    ...
+  AttributeError: 'Mammoth' object has no attribute 'somethingelse'
+
+If the 'fields' attribute is not an old-style class, it will not trigger any
+attribute generation:
+
+  >>> cave = Cave()
+  >>> cave.ignored
+  Traceback (most recent call last):
+    ...
+  AttributeError: 'Cave' object has no attribute 'ignored'
+
+A grok.EditForm is a special grok.View that renders an edit form.
+
+  >>> from zope import component
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> view = component.getMultiAdapter((manfred, request), name='edit')
+  >>> len(view.form_fields)
+  2
+  >>> [w.__name__ for w in view.form_fields]
+  ['name', 'size']
+
+It is important to keep the order of the fields:
+
+  >>> view = component.getMultiAdapter(
+  ...    (DifferentMammoth(), request), name='editdifferent')
+  >>> len(view.form_fields)
+  2
+  >>> [w.__name__ for w in view.form_fields]
+  ['size', 'name']
+
+"""
+import grok
+from zope import schema
+
+class Mammoth(grok.Model):
+    class fields:
+        name = schema.TextLine(title=u"Name")
+        size = schema.TextLine(title=u"Size", default=u"Quite normal")
+        somethingelse = None
+
+class Edit(grok.EditForm):
+    grok.context(Mammoth)
+
+class Cave(grok.Model):
+    fields = ['ignored']
+
+class DifferentMammoth(grok.Model):
+    class fields:
+        # mind the different order of fields
+        size = schema.TextLine(title=u"Size", default=u"Quite normal")
+        name = schema.TextLine(title=u"Name")
+
+class EditDifferent(grok.EditForm):
+    grok.context(DifferentMammoth)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/form.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/norender.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/form/norender.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/form/norender.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,24 @@
+"""
+Forms cannot define a render method. Here we show the case where the
+EditForm has an explicit template associate with it.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  ...
+  GrokError: It is not allowed to specify a custom 'render' method for
+  form <class 'grok.tests.form.norender.Edit'>. Forms either use the default
+  template or a custom-supplied one.
+  
+"""
+
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class Edit(grok.EditForm):
+    # not allowed to have a render method
+    def render(self):
+        return "this cannot be"
+    
+edit = grok.PageTemplate('Foo!')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/norender.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/norender2.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/form/norender2.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/form/norender2.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,22 @@
+"""
+Forms cannot define a render method. Here we show the case where the
+EditForm has no explicit template associated with it:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  ...
+  GrokError: It is not allowed to specify a custom 'render' method for
+  form <class 'grok.tests.form.norender2.Edit'>. Forms either use the default
+  template or a custom-supplied one.
+  
+"""
+
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class Edit(grok.EditForm):
+    # not allowed to have a render method
+    def render(self):
+        return "this cannot be"


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/norender2.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/schemaform.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/form/schemaform.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/form/schemaform.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,83 @@
+"""
+A grok.Model may implement one or more interfaces that are schemas:
+
+  >>> grok.grok(__name__)
+  >>> manfred = Mammoth()
+
+A grok.EditForm is a special grok.View that renders an edit form.
+
+  >>> from zope import component
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> view = component.getMultiAdapter((manfred, request), name='edit')
+  >>> len(view.form_fields)
+  2
+  >>> [w.__name__ for w in view.form_fields]
+  ['name', 'size']
+
+When there are multiple schemas in play, we get all the fields:
+
+  >>> view = component.getMultiAdapter((Manfred(), request), name='edit2')
+  >>> len(view.form_fields)
+  3
+  >>> [w.__name__ for w in view.form_fields]
+  ['can_talk', 'name', 'size']
+
+Schema fields and model level fields are combined:
+
+  >>> view = component.getMultiAdapter(
+  ...    (AnotherMammoth(), request), name='edit3')
+  >>> len(view.form_fields)
+  3
+  >>> [w.__name__ for w in view.form_fields]
+  ['can_talk', 'name', 'size']
+
+If the context is an interface instead of a model directly, the fields
+will be retrieved from that interface, and that interface only:
+
+  >>> view = component.getMultiAdapter(
+  ...   (YetAnotherMammoth(), request), name='edit4')
+  >>> len(view.form_fields)
+  2
+  >>> [w.__name__ for w in view.form_fields]
+  ['alpha', 'beta']
+
+"""
+import grok
+from zope import interface, schema
+
+class IMammoth(interface.Interface):
+    name = schema.TextLine(title=u"Name")
+    size = schema.TextLine(title=u"Size", default=u"Quite normal")
+
+class Mammoth(grok.Model):
+    interface.implements(IMammoth)
+
+class Edit(grok.EditForm):
+    grok.context(Mammoth)
+
+class IMovieCharacter(interface.Interface):
+    can_talk = schema.Bool(title=u'Can talk', default=False)
+
+class Manfred(Mammoth):
+    interface.implements(IMovieCharacter)
+
+class Edit2(grok.EditForm):
+    grok.context(Manfred)
+    
+class AnotherMammoth(Mammoth):
+    class fields:
+        can_talk = schema.Bool(title=u'Can talk', default=False)
+
+class Edit3(grok.EditForm):
+    grok.context(AnotherMammoth)
+
+class IYetAnotherMammoth(interface.Interface):
+    alpha = schema.TextLine(title=u'alpha')
+    beta = schema.TextLine(title=u'beta')
+
+class YetAnotherMammoth(grok.Model):
+    interface.implements(IYetAnotherMammoth)
+
+class Edit4(grok.EditForm):
+    grok.context(IYetAnotherMammoth)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/schemaform.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/schemainherit.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/form/schemainherit.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/form/schemainherit.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,64 @@
+"""
+A grok.Model may implement a schema that inherits from another one:
+
+  >>> grok.grok(__name__)
+  >>> manfred = Mammoth()
+
+  >>> from zope import component
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+
+Without AutoFields, just a simple edit form:
+
+  >>> view = component.getMultiAdapter((manfred, request), name='edit')
+  >>> len(view.form_fields)
+  3
+  >>> [w.__name__ for w in view.form_fields]
+  ['name', 'size', 'speciality']
+
+With AutoFields:
+
+  >>> view = component.getMultiAdapter((manfred, request), name='edit2')
+  >>> len(view.form_fields)
+  3
+  >>> [w.__name__ for w in view.form_fields]
+  ['name', 'size', 'speciality']
+
+  >>> antimanfred = YetAnotherMammoth()
+  >>> view = component.getMultiAdapter((antimanfred, request), name='edit3')
+  >>> len(view.form_fields)
+  3
+  >>> [w.__name__ for w in view.form_fields]
+  ['name', 'size', 'speciality']
+"""
+import grok
+from zope import interface, schema
+
+class IMammoth(interface.Interface):
+    name = schema.TextLine(title=u"Name")
+    size = schema.TextLine(title=u"Size", default=u"Quite normal")
+
+class ISpecialMammoth(IMammoth):
+    speciality = schema.TextLine(title=u"Speciality")
+
+class Mammoth(grok.Model):
+    interface.implements(ISpecialMammoth)
+
+class Edit(grok.EditForm):
+    grok.context(Mammoth)
+
+class Edit2(grok.EditForm):
+    grok.context(Mammoth)
+
+    form_fields = grok.AutoFields(Mammoth)
+
+# situation where subclass implements something on top of base class
+class AnotherMammoth(grok.Model):
+    interface.implements(IMammoth)
+
+class YetAnotherMammoth(AnotherMammoth):
+    interface.implements(ISpecialMammoth)
+
+class Edit3(grok.EditForm):
+    grok.context(YetAnotherMammoth)
+    


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/form/schemainherit.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/continue_scanning.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/continue_scanning.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/continue_scanning.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,41 @@
+"""
+A Grokker can declare that scanning should continue, so that other Grokkers can
+still perform actions on the grokked components.
+
+Here we define AlphaGrokker which has higher priority than BetaGrokker but does
+not block BetaGrokker from picking up the same component::
+
+    >>> grok.grok(__name__)
+
+In the fixture there is AlphaBetaSub that inherits from both Alpha and Beta.
+Thus, both Grokkers are executed, with AlphaGrokker coming before BetaGrokker::
+
+    >>> grok.grok('grok.tests.grokker.continue_scanning_fixture')
+    alpha
+    beta
+
+"""
+import grok
+
+
+class Alpha(object):
+    pass
+
+class Beta(object):
+    pass
+
+class AlphaGrokker(grok.ClassGrokker):
+    component_class = Alpha
+    priority = 1 # we need to go before BetaGrokker
+
+    def grok(self, name, factory, context, module_info, templates):
+        print "alpha"
+        return True
+
+class BetaGrokker(grok.ClassGrokker):
+    component_class = Beta
+
+    def grok(self, name, factory, context, module_info, templates):
+        print "beta"
+        return True
+    


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/continue_scanning.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/continue_scanning_fixture.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/continue_scanning_fixture.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/continue_scanning_fixture.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,4 @@
+from grok.tests.grokker.continue_scanning import Alpha, Beta
+
+class AlphaBetaSub(Alpha, Beta):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/continue_scanning_fixture.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/grokcomponent.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/grokcomponent.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/grokcomponent.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,61 @@
+"""
+
+Let's first grok the meta module to define some basic grokkers::
+
+  >>> import grok
+  >>> grok.grok('grok.meta')
+  
+It is possible to grok an individual component. Let's define an adapter::
+
+  >>> from zope.interface import Interface
+  >>> class IMyInterface(Interface):
+  ...   pass
+  >>> class SomeClass(object):
+  ...   pass
+  >>> class MyAdapter(grok.Adapter):
+  ...   grok.provides(IMyInterface)
+  ...   grok.context(SomeClass)
+
+To grok this adapter, you can simply write this::
+
+  >>> grok.grok_component('MyAdapter', MyAdapter)
+  True
+
+We can now use the adapter::
+
+  >>> instance = SomeClass()
+  >>> adapter = IMyInterface(instance)
+  >>> isinstance(adapter, MyAdapter)
+  True
+
+We can use grok_component with only two arguments because we know the
+adapter grokker is not looking for more. Sometimes we need to supply
+an extra argument however::
+
+  >>> class ISecondInterface(Interface):
+  ...   pass
+  >>> class SecondAdapter(grok.Adapter):
+  ...   grok.provides(ISecondInterface)
+
+This adapter does not supply its own context. Trying to do what we did
+before will therefore fail::
+
+  >>> grok.grok_component('SecondAdapter', SecondAdapter)
+  Traceback (most recent call last):
+    ...
+  GrokError: No module-level context for <class 'grok.tests.grokker.grokcomponent.SecondAdapter'>, please use grok.context.
+
+So we need to supply the context ourselves::
+
+  >>> grok.grok_component('SecondAdapter', SecondAdapter, context=SomeClass)
+  True
+
+Now we can use the SecondAdapter as well::
+
+  >>> adapter = ISecondInterface(instance)
+  >>> isinstance(adapter, SecondAdapter)
+  True
+
+The next optional argument is module_info and the final argument is
+templates.
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/grokcomponent.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,27 @@
+"""
+
+We define a grokker AlphaGrokker for a component called Alpha. We first need to
+grok the module defining the grokkers, in order to get them registered.
+
+Usually this would be triggered from a meta.zcml in a package, that would grok
+the module containing the grokkers (e.g. meta.py).
+
+We do it manually now::
+
+  >>> import grok
+  >>> grok.grok('grok.tests.grokker.onlyonce_fixture._meta')
+
+This _meta.py module then will be grokked again during 'normal' grok time. Grok
+will not re-register the grokkers as this could have unwanted side-effects. It
+will grok the components of course.
+
+NOTE: the module is called _meta to make sure it is grokked (although its
+grokker registration should be ignored) before the other files. The modules are
+picked up in alphabetical order.
+
+To simulate this, we grok the whole package::
+
+  >>> grok.grok('grok.tests.grokker.onlyonce_fixture')
+  alpha
+
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# fixture package
\ No newline at end of file


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/_meta.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/_meta.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/_meta.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+import martian
+from component import Alpha
+
+class AlphaGrokker(martian.ClassGrokker):
+    component_class = Alpha
+
+    def grok(self, name, factory, context, module_info, templates):
+        print "alpha"
+        return True


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/_meta.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/component.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/component.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/component.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,4 @@
+import grok
+
+class Alpha(object):
+    grok.baseclass()


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/component.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/implementation.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/implementation.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/implementation.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,4 @@
+from component import Alpha
+
+class AlphaSub(Alpha):
+    pass
\ No newline at end of file


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/onlyonce_fixture/implementation.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/priority.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/priority.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/priority.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,54 @@
+"""
+We define grokkers for the three base classes Alpha, Beta, and Gamma with different
+priorities:
+ 
+- AlphaGrokker with priority 0 (default)
+- BetaGrokker with priority 1
+- GammaGrokker with priority -1
+
+    >>> grok.grok(__name__)
+
+We grok a module that implements subclasses for Alpha, Beta, and Gamma and our
+grokkers get executed in the order of priority (highest first)::
+
+    >>> grok.grok('grok.tests.grokker.priority_fixture')
+    beta
+    alpha
+    gamma
+
+"""
+import grok
+
+
+class Alpha(object):
+    pass
+
+
+class Beta(object):
+    pass
+
+class Gamma(object):
+    pass
+
+class AlphaGrokker(grok.ClassGrokker):
+    component_class = Alpha
+
+    def grok(self, name, factory, context, module_info, templates):
+        print "alpha"
+        return True
+
+class BetaGrokker(grok.ClassGrokker):
+    component_class = Beta
+    priority = 1
+
+    def grok(self, name, factory, context, module_info, templates):
+        print "beta"
+        return True
+    
+class GammaGrokker(grok.ClassGrokker):
+    component_class = Gamma
+    priority = -1
+
+    def grok(self, name, factory, context, module_info, templates):
+        print "gamma"
+        return True


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/priority.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/priority_fixture.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/priority_fixture.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/priority_fixture.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,10 @@
+import grok.tests.grokker.priority
+
+class AlphaSub(grok.tests.grokker.priority.Alpha):
+    pass
+
+class BetaSub(grok.tests.grokker.priority.Beta):
+    pass
+
+class GammaSub(grok.tests.grokker.priority.Gamma):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/grokker/priority_fixture.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/json/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/json/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/json/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/json/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/json/nocontext.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/json/nocontext.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/json/nocontext.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,16 @@
+"""
+
+Context-determination follows the same rules as for adapters. We just check
+whether it's hooked up at all:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: No module-level context for
+  <class 'grok.tests.json.nocontext.TestJSON'>, please use grok.context.
+
+"""
+import grok
+
+class TestJSON(grok.JSON):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/json/nocontext.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/json/view_lookup.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/json/view_lookup.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/json/view_lookup.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,38 @@
+"""
+
+The JSON grokker registers a view for each method of the JSON class.
+So we should be able to search for view by method name.
+
+  >>> grok.grok(__name__)
+  >>> mammoth = Mammoth()
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope.component import getMultiAdapter
+  >>> view = getMultiAdapter((mammoth, request), name='run')
+
+The 'run' method/view returns json data, but it looks just like python.
+
+  >>> view()
+  '{"me": "grok"}'
+
+Let's try calling another method::
+
+  >>> view = getMultiAdapter((mammoth, request), name='another')
+  >>> view()
+  '{"another": "grok"}'
+  
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class MammothView(grok.JSON):
+    grok.context(Mammoth)
+
+    def run(self):
+        return { 'me': 'grok' }
+
+    def another(self):
+        return { 'another': 'grok'}
+    


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/json/view_lookup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/security/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/security/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# make this directory a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+"""
+A permission has to be defined first (using grok.define_permission for
+example) before it can be used in grok.require().
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission.MissingPermission'>. Use grok.define_permission first.
+
+"""
+
+import grok
+import zope.interface
+
+class MissingPermission(grok.View):
+    grok.context(zope.interface.Interface)
+    grok.require('doesnt.exist')
+
+    def render(self):
+        pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_json.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_json.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_json.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+"""
+A permission has to be defined first (using grok.define_permission for
+example) before it can be used in grok.require() in an JSON class.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_json.MissingPermission'>. Use grok.define_permission first.
+
+"""
+
+import grok
+import zope.interface
+
+class MissingPermission(grok.JSON):
+    grok.context(zope.interface.Interface)
+    grok.require('doesnt.exist')
+
+    def foo(self):
+        pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_json.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_json2.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_json2.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_json2.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+"""
+A permission has to be defined first (using grok.define_permission for
+example) before it can be used in @grok.require().
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_json2.MissingPermission'>. Use grok.define_permission first.
+
+"""
+
+import grok
+import zope.interface
+
+class MissingPermission(grok.JSON):
+    grok.context(zope.interface.Interface)
+
+    @grok.require('doesnt.exist')
+    def foo(self):
+        pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_json2.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+"""
+A permission has to be defined first (using grok.define_permission for
+example) before it can be used in grok.require() in an XMLRPC class.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_xmlrpc.MissingPermission'>. Use grok.define_permission first.
+
+"""
+
+import grok
+import zope.interface
+
+class MissingPermission(grok.XMLRPC):
+    grok.context(zope.interface.Interface)
+    grok.require('doesnt.exist')
+
+    def foo(self):
+        pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc2.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc2.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc2.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+"""
+A permission has to be defined first (using grok.define_permission for
+example) before it can be used in @grok.require().
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_xmlrpc2.MissingPermission'>. Use grok.define_permission first.
+
+"""
+
+import grok
+import zope.interface
+
+class MissingPermission(grok.XMLRPC):
+    grok.context(zope.interface.Interface)
+
+    @grok.require('doesnt.exist')
+    def foo(self):
+        pass
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc2.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc3.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc3.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc3.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,24 @@
+"""
+A permission has to be defined first (using grok.define_permission for
+example) before it can be used in grok.require() in an XMLRPC class. This
+is even the case for a default permission that is never used.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+   ...
+  GrokError: Undefined permission 'doesnt.exist' in <class 'grok.tests.security.missing_permission_xmlrpc3.MissingPermission'>. Use grok.define_permission first.
+
+"""
+
+import grok
+import zope.interface
+
+grok.define_permission('foo')
+
+class MissingPermission(grok.XMLRPC):
+    grok.context(zope.interface.Interface)
+    grok.require('doesnt.exist')
+
+    @grok.require('foo')
+    def foo(self):
+        pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/missing_permission_xmlrpc3.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,22 @@
+"""
+Multiple calls of grok.require in one class are not allowed.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: grok.require was called multiple times in <class 'grok.tests.security.multiple_require.MultipleView'>. It may only be set once for a class.
+
+"""
+import grok
+import zope.interface
+
+grok.define_permission('permission.1')
+grok.define_permission('permission.2')
+
+class MultipleView(grok.View):
+    grok.context(zope.interface.Interface)
+    grok.require('permission.1')
+    grok.require('permission.2')
+
+    def render(self):
+        pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require_json.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require_json.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require_json.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,22 @@
+"""
+Multiple calls of grok.require in one class are not allowed.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: grok.require was called multiple times in <class 'grok.tests.security.multiple_require_json.MultipleJSON'>. It may only be set once for a class.
+  
+"""
+import grok
+import zope.interface
+
+grok.define_permission('permission.1')
+grok.define_permission('permission.2')
+
+class MultipleJSON(grok.JSON):
+    grok.context(zope.interface.Interface)
+    grok.require('permission.1')
+    grok.require('permission.2')
+
+    def render(self):
+        pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require_json.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require_xmlrpc.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require_xmlrpc.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require_xmlrpc.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,21 @@
+"""
+Multiple calls of grok.require in one class are not allowed.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+     ...
+  GrokError: grok.require was called multiple times in <class 'grok.tests.security.multiple_require_xmlrpc.MultipleXMLRPC'>. It may only be set once for a class.
+"""
+import grok
+import zope.interface
+
+grok.define_permission('permission.1')
+grok.define_permission('permission.2')
+
+class MultipleXMLRPC(grok.XMLRPC):
+    grok.context(zope.interface.Interface)
+    grok.require('permission.1')
+    grok.require('permission.2')
+
+    def render(self):
+        pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/multiple_require_xmlrpc.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/view_decorator.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/security/view_decorator.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/security/view_decorator.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,21 @@
+"""
+Using the @grok.require decorator in a view class is not allowed.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  GrokError: The @grok.require decorator is used for method 'render' in view <class 'grok.tests.security.view_decorator.BogusView'>. It may only be used for XML-RPC methods.
+
+
+"""
+
+import grok
+import zope.interface
+
+grok.define_permission('bogus.perm')
+
+class BogusView(grok.View):
+    grok.context(zope.interface.Interface)
+
+    @grok.require('bogus.perm')
+    def render(self):
+        pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/security/view_decorator.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/site/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/site/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/site/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/site/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/site/site.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/site/site.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/site/site.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,51 @@
+"""
+A site can be created by mixing in grok.Site into a grok.Model or
+grok.Container.
+
+  >>> grok.grok(__name__)
+
+  >>> from zope import interface
+  >>> from zope.app.component.interfaces import IPossibleSite, ISite
+  >>> manfred = Mammoth()
+  >>> IPossibleSite.providedBy(manfred)
+  True
+  >>> herd = Herd()
+  >>> IPossibleSite.providedBy(herd)
+  True
+  >>> nonsite = NonSite()
+  >>> IPossibleSite.providedBy(nonsite)
+  False
+  >>> nonsitecontainer = NonSiteContainer()
+  >>> IPossibleSite.providedBy(nonsitecontainer)
+  False
+
+While manfred and herd are possible sites, they are not yet sites;
+
+  >>> ISite.providedBy(manfred)
+  False
+  >>> ISite.providedBy(herd)
+  False
+  
+When a site is added to a container it will be initialized as a site (
+when the ObjectAddedEvent is fired):
+
+  >>> nonsitecontainer['manfred'] = manfred
+  >>> ISite.providedBy(manfred)
+  True
+  >>> nonsitecontainer['herd'] = herd
+  >>> ISite.providedBy(herd)
+  True
+"""
+import grok
+
+class Mammoth(grok.Model, grok.Site):
+    pass
+
+class Herd(grok.Container, grok.Site):
+    pass
+
+class NonSite(grok.Model):
+    pass
+
+class NonSiteContainer(grok.Container):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/site/site.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/static/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/static/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,11 @@
+"""
+When a package contains a 'static' resource directory, it must not also contain
+a module called 'static.py':
+
+  >>> import grok
+  >>> grok.grok('grok.tests.static.statichaspy_fixture')
+  Traceback (most recent call last):
+    ...
+  GrokError: A package can not contain both a 'static' resource directory
+  and a module named 'static.py'
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy_fixture/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy_fixture/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy_fixture/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy_fixture/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy_fixture/static.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy_fixture/static.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy_fixture/static.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,2 @@
+# This is an error: there can be no python module named 'static.py' when there
+# is a 'static' resource directory


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/statichaspy_fixture/static.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+"""
+It is an error for the 'static' directory to be a python package:
+
+  >>> import grok
+  >>> grok.grok('grok.tests.static.staticispackage_fixture')
+  Traceback (most recent call last):
+    ...
+  GrokError: The 'static' resource directory must not be a python package.
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage_fixture/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage_fixture/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage_fixture/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage_fixture/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage_fixture/static/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage_fixture/static/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage_fixture/static/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/static/staticispackage_fixture/static/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/test_grok.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/test_grok.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/test_grok.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,43 @@
+import unittest
+from pkg_resources import resource_listdir
+from zope.testing import doctest, cleanup
+import zope.component.eventtesting
+
+def setUpZope(test):
+    zope.component.eventtesting.setUp(test)
+
+def cleanUpZope(test):
+    cleanup.cleanUp()
+
+def suiteFromPackage(name):
+    files = resource_listdir(__name__, name)
+    suite = unittest.TestSuite()
+    for filename in files:
+        if not filename.endswith('.py'):
+            continue
+        if filename.endswith('_fixture.py'):
+            continue
+        if filename == '__init__.py':
+            continue
+
+        dottedname = 'grok.tests.%s.%s' % (name, filename[:-3])
+        test = doctest.DocTestSuite(dottedname,
+                                    setUp=setUpZope,
+                                    tearDown=cleanUpZope,
+                                    optionflags=doctest.ELLIPSIS+
+                                    doctest.NORMALIZE_WHITESPACE)
+
+        suite.addTest(test)
+    return suite
+
+def test_suite():
+    suite = unittest.TestSuite()
+    for name in ['adapter', 'error', 'view', 'event', 'security',
+                 'zcml', 'static', 'utility', 'xmlrpc', 'json', 'container',
+                 'traversal', 'form', 'site', 'grokker', 'directive', 'util',
+                 'baseclass', 'annotation', 'application']:
+        suite.addTest(suiteFromPackage(name))
+    return suite
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/test_grok.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/traversal/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/traversal/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/traversal/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/traversal/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/util/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/util/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/util/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/util/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/util/class_annotation.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/util/class_annotation.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/util/class_annotation.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+"""
+  >>> util.class_annotation_list(B, 'grok.foo', None)
+  [5, 7]
+  >>> util.class_annotation_list(B2, 'grok.foo', None)
+  [5]
+  >>> util.class_annotation_list(C, 'grok.foo', None)
+  [5, 7, 8]
+  >>> util.class_annotation_list(C2, 'grok.foo', None)
+  [5, 7, 9]
+
+"""
+import grok
+from martian import util
+
+class A(object):
+    __grok_foo__ = [5]
+
+class B(A):
+    __grok_foo__ = [7]
+
+class B2(A):
+    pass
+
+class C(B, B2):
+    __grok_foo__ = [8]
+
+class C2(B2, B):
+    __grok_foo__ = [9]


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/util/class_annotation.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsmany.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsmany.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsmany.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,21 @@
+"""
+Subclasses of grok.GlobalUtility that implement more than one interface must
+specify which interface to use for the registration:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: <class 'grok.tests.utility.implementsmany.Club'> is implementing
+  more than one interface (use grok.provides to specify which one to use).
+"""
+import grok
+from zope import interface
+
+class IClub(interface.Interface):
+    pass
+
+class ISpikyClub(interface.Interface):
+    pass
+
+class Club(grok.GlobalUtility):
+    grok.implements(IClub, ISpikyClub)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsmany.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsmany2.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsmany2.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsmany2.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,24 @@
+"""
+Subclasses of grok.GlobalUtility that implement more than one interface must
+specify which interface to use for the registration:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: <class 'grok.tests.utility.implementsmany2.Club'> is implementing
+  more than one interface (use grok.provides to specify which one to use).
+"""
+import grok
+from zope import interface
+
+class IClub(interface.Interface):
+    pass
+
+class ISpikyClub(interface.Interface):
+    pass
+
+class Club(object):
+    grok.implements(IClub, ISpikyClub)
+
+grok.global_utility(Club)
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsmany2.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsnone.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsnone.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsnone.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,13 @@
+"""
+Subclasses of grok.GlobalUtility must implement exactly one interface:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: <class 'grok.tests.utility.implementsnone.Club'> must
+  implement at least one interface (use grok.implements to specify).
+"""
+import grok
+
+class Club(grok.GlobalUtility):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsnone.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsnone2.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsnone2.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsnone2.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,15 @@
+"""
+Subclasses of grok.GlobalUtility must implement exactly one interface:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: <class 'grok.tests.utility.implementsnone2.Club'> must
+  implement at least one interface (use grok.implements to specify).
+"""
+import grok
+
+class Club(object):
+    pass
+
+grok.global_utility(Club)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/implementsnone2.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsmany.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsmany.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsmany.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,30 @@
+"""
+Anything can be registered as a local utility. If it implements a single
+interface, there is no need to specify which interface it provides.
+
+In this test, the utility implements more than one interface, so it cannot be
+registered as a local utility.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: <class 'grok.tests.utility.local_implementsmany.Fireplace'>
+  is implementing more than one interface (use grok.provides to specify
+  which one to use).
+
+"""
+
+import grok
+from zope import interface
+
+class IHome(interface.Interface):
+    pass
+
+class IFireplace(interface.Interface):
+    pass
+
+class Fireplace(object):
+    interface.implements(IHome, IFireplace)
+
+class Cave(grok.Model, grok.Site):
+    grok.local_utility(Fireplace)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsmany.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsnone.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsnone.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsnone.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,23 @@
+"""
+Anything can be registered as a local utility. If it implements a single
+interface, there is no need to specify which interface it provides.
+
+In this test, the utility does not implement any interface, so it cannot be
+registered as a local utility.
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: <class 'grok.tests.utility.local_implementsnone.Fireplace'>
+  must implement at least one interface (use grok.implements to specify).
+
+"""
+
+import grok
+from zope import interface
+
+class Fireplace(object):
+    pass
+
+class Cave(grok.Model, grok.Site):
+    grok.local_utility(Fireplace)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsnone.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsnone2.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsnone2.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsnone2.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,25 @@
+"""
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: Cannot determine which interface to use for utility registration of
+  <class 'grok.tests.utility.local_implementsnone2.Fireplace'> in site
+  <class 'grok.tests.utility.local_implementsnone2.Cave'>. It implements
+  an interface that is a specialization of an interface implemented
+  by grok.LocalUtility. Specify the interface by either using grok.provides on
+  the utility or passing 'provides' to grok.local_utility.
+
+"""
+
+import grok
+from zope import interface
+import persistent
+
+class ISpecialPersistent(persistent.interfaces.IPersistent):
+    pass
+
+class Fireplace(grok.LocalUtility):
+    grok.implements(ISpecialPersistent)
+
+class Cave(grok.Model, grok.Site):
+    grok.local_utility(Fireplace)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/local_implementsnone2.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/utility.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/utility.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/utility.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,180 @@
+"""
+Global utilities can be created by subclassing grok.GlobalUtility:
+
+  >>> grok.grok(__name__)
+  >>> from zope import component
+
+  >>> normal_club = component.getUtility(IClub)
+  >>> IClub.providedBy(normal_club)
+  True
+  >>> isinstance(normal_club, NormalClub)
+  True
+
+Named utilities are registered using grok.name:
+
+  >>> huge_club = component.getUtility(IClub, name='huge')
+  >>> IClub.providedBy(huge_club)
+  True
+  >>> isinstance(huge_club, HugeClub)
+  True
+
+A utility can explicitly specify which interface it should be looked up with.
+
+  >>> spiky_club = component.getUtility(IClub, name='spiky')
+  >>> isinstance(spiky_club, SpikyClub)
+  True
+
+  >>> component.getUtility(ISpikyClub, name='spiky')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: (<InterfaceClass grok.tests.utility.utility.ISpikyClub>,
+                         'spiky')
+
+If a utility implements more than one interface, it has to specify the one to
+use with 'grok.provides':
+
+  >>> nightclub = component.getUtility(INightClub)
+  >>> INightClub.providedBy(nightclub)
+  True
+  >>> isinstance(nightclub, NightClub)
+  True
+
+Utilities (including classes that do not subclass from grok.GlobalUtility) can
+be (re-)registered using grok.global_utility:
+
+  >>> fireplace = component.getUtility(IFireplace)
+  >>> IFireplace.providedBy(fireplace)
+  True
+  >>> isinstance(fireplace, Fireplace)
+  True
+
+  >>> fireplace = component.getUtility(IFireplace, name='hot')
+  >>> IFireplace.providedBy(fireplace)
+  True
+  >>> isinstance(fireplace, Fireplace)
+  True
+
+  >>> home = component.getUtility(IHome)
+  >>> IHome.providedBy(home)
+  True
+  >>> isinstance(home, Home)
+  True
+
+  >>> night = component.getUtility(INightClub, name='cool')
+  >>> IClub.providedBy(night)
+  True
+  >>> isinstance(night, NightClub)
+  True
+  
+  >>> spiky = component.getUtility(ISpikyClub)
+  >>> ISpikyClub.providedBy(spiky)
+  True
+  >>> isinstance(spiky, NightClub)
+  True
+
+When re-registering a grok.GlobalUtility, the directives grok.name and
+grok.provides on the class will be used, but can be overriden in the
+grok.global_utility directive:
+
+  >>> small = component.getUtility(ISmallClub, name='tiny')
+  >>> ISmallClub.providedBy(small)
+  True
+  >>> isinstance(small, SmallClub)
+  True
+
+  >>> small2 = component.getUtility(ITinyClub, name='tiny')
+  >>> ISmallClub.providedBy(small2)
+  True
+  >>> isinstance(small2, SmallClub)
+  True
+  >>> small is not small2
+  True
+
+  >>> small3 = component.getUtility(ISmallClub, name='small')
+  >>> ISmallClub.providedBy(small3)
+  True
+  >>> isinstance(small3, SmallClub)
+  True
+  >>> small3 is not small2 and small3 is not small
+  True
+
+Normally one registers a utility factory, such as the class, as a
+global utility. It is also possible to register an arbitrary object directly
+as a global utility. You do this by passing a 'direct' argument set to
+'True'. This can be useful if one needs to register functions (such
+as factory functions) that can be looked up as a utility, or if the
+class you want to register as a global utility has an __init__ that
+takes arguments, where you want to do the instantiation yourself.
+Let's look up an instance we registered this way:
+
+  >>> small4 = component.getUtility(ISmallClub, name='smallish')
+  >>> ISmallClub.providedBy(small4)
+  True
+  >>> isinstance(small4, SmallClub)
+  True
+  
+"""
+
+import grok
+from zope import interface
+
+class IClub(interface.Interface):
+    pass
+
+class ISpikyClub(IClub):
+    pass
+
+class ISmallClub(IClub):
+    pass
+
+class ITinyClub(IClub):
+    pass
+
+class INightClub(interface.Interface):
+    pass
+
+class NormalClub(grok.GlobalUtility):
+    grok.implements(IClub)
+
+class HugeClub(grok.GlobalUtility):
+    grok.implements(IClub)
+    grok.name('huge')    
+
+class SpikyClub(grok.GlobalUtility):
+    grok.implements(ISpikyClub)
+    grok.provides(IClub)
+    grok.name('spiky')
+
+class NightClub(grok.GlobalUtility):
+    grok.implements(INightClub, ISpikyClub)
+    grok.provides(INightClub)
+
+class SmallClub(grok.GlobalUtility):
+    grok.implements(ISmallClub, ITinyClub)
+    grok.provides(ISmallClub)
+    grok.name('tiny')
+
+class IFireplace(interface.Interface):
+    pass
+
+class IHome(interface.Interface):
+    pass
+
+class Fireplace(object):
+    grok.implements(IFireplace)
+
+class Home(object):
+    grok.implements(IFireplace, IHome)
+
+grok.global_utility(Fireplace)
+grok.global_utility(Fireplace, name='hot')
+grok.global_utility(Home, provides=IHome)
+
+grok.global_utility(NightClub, name='cool')
+grok.global_utility(NightClub, provides=ISpikyClub)
+
+grok.global_utility(SmallClub, provides=ITinyClub)
+grok.global_utility(SmallClub, name='small')
+
+grok.global_utility(SmallClub(), name='smallish',
+                    direct=True)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/utility/utility.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/ambiguouscontext.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/ambiguouscontext.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/ambiguouscontext.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,21 @@
+"""
+Templates with ambiguous context cannot be grokked:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: Multiple possible contexts for
+  <class 'grok.tests.view.ambiguouscontext.Club'>, please use grok.context.
+
+"""
+
+import grok
+
+class Cave(grok.Model):
+    pass
+
+class Mammoth(grok.Model):
+    pass
+
+class Club(grok.View):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/ambiguouscontext.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirandinlinetemplate.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirandinlinetemplate.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirandinlinetemplate.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,21 @@
+"""
+If multiple templates can be found, one in the module and one in the
+template directory, there is an error:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: Conflicting templates found for name 'cavepainting' in module
+  <module 'grok.tests.view.dirandinlinetemplate' from '...'>,
+  both inline and in template directory '...dirandinlinetemplate_templates'.
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class CavePainting(grok.View):
+    pass
+
+cavepainting = grok.PageTemplate("nothing")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirandinlinetemplate.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirandinlinetemplate_templates/cavepainting.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirandinlinetemplate_templates/cavepainting.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirandinlinetemplate_templates/cavepainting.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+nothing

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,36 @@
+"""
+Templates can also be found in a directory with the same name as the module:
+
+  >>> grok.grok(__name__)
+  
+  >>> manfred = Mammoth()
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+  >>> view = component.getMultiAdapter((manfred, request), name='cavepainting')
+  >>> print view()
+  <html>
+  <body>
+  A cave painting.
+  </body>
+  </html>
+
+  >>> view = component.getMultiAdapter((manfred, request), name='food')
+  >>> print view()
+  <html>
+  <body>
+  ME GROK EAT MAMMOTH!
+  </body>
+  </html>
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class CavePainting(grok.View):
+    pass
+
+class Food(grok.View):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate_templates/cavepainting.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate_templates/cavepainting.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate_templates/cavepainting.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+A cave painting.
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate_templates/food.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate_templates/food.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplate_templates/food.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+ME GROK EAT MAMMOTH!
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplateandrender.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplateandrender.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplateandrender.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+"""
+A View may either have an associated template or a render-method. Here
+we check that this also works for templates in a template-directory:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: Multiple possible ways to render view
+  <class 'grok.tests.view.dirtemplateandrender.CavePainting'>.
+  It has both a 'render' method as well as an associated template.
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class CavePainting(grok.View):
+    def render(self):
+        pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplateandrender.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplateandrender_templates/cavepainting.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplateandrender_templates/cavepainting.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplateandrender_templates/cavepainting.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+A cave painting.
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,12 @@
+"""
+A template directory may only contain recognized template files:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: Unrecognized file 'invalid.txt' in template directory '...dirtemplatesonly_templates'.
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+nothing to see here

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly_templates/invalid.txt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly_templates/invalid.txt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly_templates/invalid.txt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+nothing to see here


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/dirtemplatesonly_templates/invalid.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/eithertemplateorrender.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/eithertemplateorrender.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/eithertemplateorrender.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+"""
+Only one, either a template, or render() can be specified:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: Multiple possible ways to render view
+  <class 'grok.tests.view.eithertemplateorrender.CavePainting'>.
+  It has both a 'render' method as well as an associated template.
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class CavePainting(grok.View):
+    def render(self):
+        pass
+
+cavepainting = grok.PageTemplate("nothing")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/eithertemplateorrender.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/explicitimplicittemplate.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/explicitimplicittemplate.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/explicitimplicittemplate.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,24 @@
+"""
+It is too confusing to have a template that would be implicitly
+associated with a view while that view already refers to another
+template using grok.template.  Therefore there is an error:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: Multiple possible templates for view
+  <class 'grok.tests.view.explicitimplicittemplate.Painting'>.
+  It uses grok.template('cavepainting'), but there is also a template
+  called 'painting'.
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class Painting(grok.View):
+    grok.template('cavepainting')
+
+cavepainting = grok.PageTemplate("GROK CAVEPAINT MAMMOTH!")
+painting = grok.PageTemplate("GROK PAINT MAMMOTH!")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/explicitimplicittemplate.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inline.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inline.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inline.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,65 @@
+"""
+Templates can be specified in the same module as the view,
+using a variable named `viewname_pt`:
+
+  >>> grok.grok(__name__)
+  
+  >>> manfred = Mammoth()
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+  >>> view = component.getMultiAdapter((manfred, request), name='cavepainting')
+  >>> print view()
+  <html>
+  <body>
+  <h1>Mammoth Cave Painting</h1>
+  <ul>
+    <li><zope.publisher.browser.TestRequest instance URL=http://127.0.0.1></li>
+    <li><grok.tests.view.inline.CavePainting object at 0x...></li>
+    <li><grok.tests.view.inline.Mammoth object at 0x...></li>
+    <li><zope.app.pagetemplate.engine.TraversableModuleImporter object at 0x...></li>
+  </ul>
+  </body>
+  </html>
+
+Note that the CavePainting instance is bound to the ``view`` name in
+the template.  This shows that the association of inline PageTemplate
+and the view class is successful.
+
+Finding a template does not depend on the view name, but on the class
+name:
+
+  >>> view = component.getMultiAdapter((manfred, request), name='hunting')
+  >>> print view()
+  <html><body><h1>GROK HUNT MAMMOTH!</h1></body></html>
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class CavePainting(grok.View):
+    pass
+
+cavepainting = grok.PageTemplate("""\
+<html>
+<body>
+<h1 tal:content="string:Mammoth Cave Painting"/>
+<ul>
+  <li tal:content="structure python:repr(request)" />
+  <li tal:content="structure nocall:view" />
+  <li tal:content="structure nocall:context" />
+  <li tal:content="structure nocall:modules" />
+</ul>
+</body>
+</html>
+""")
+
+class Hunt(grok.View):
+    grok.name('hunting')
+
+hunt = grok.PageTemplate("""\
+<html><body><h1>GROK HUNT MAMMOTH!</h1></body></html>
+""")
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inline.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inline_unassociated.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inline_unassociated.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inline_unassociated.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+"""
+Inline templates that are not associated with a view class will
+provoke an error:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  ...
+  GrokError: 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).
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+club = grok.PageTemplate("""\
+<html><body><h1>GROK CLUB MAMMOTH!</h1></body></html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inline_unassociated.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inlinebogus.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inlinebogus.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inlinebogus.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,16 @@
+# -*- coding: latin-1 -*-
+"""
+We do not accept bogus inline template such as ones that contain
+encoded strings:
+
+  >>> import grok
+  >>> grok.PageTemplate('''
+  ... <html>
+  ... <body><h1 tal:content="string:Mammoth Cave Painting"/>
+  ... <p>ööö</p>
+  ... </body>
+  ... </html>''')
+  Traceback (most recent call last):
+    ...
+  ValueError: Invalid page template. Page templates must be unicode or ASCII.
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/inlinebogus.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/missingcontext.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/missingcontext.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/missingcontext.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,15 @@
+"""
+Views without a context cannot be grokked:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: No module-level context for
+  <class 'grok.tests.view.missingcontext.Club'>, please use grok.context.
+
+"""
+
+import grok
+
+class Club(grok.View):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/missingcontext.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/namemultiple.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/namemultiple.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/namemultiple.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+"""
+You can't call grok.name multiple times for a view
+
+  >>> import grok.tests.view.namemultiple_fixture
+  Traceback (most recent call last):
+    ...
+  GrokImportError: grok.name can only be called once per class.
+
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/namemultiple.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/namemultiple_fixture.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/namemultiple_fixture.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/namemultiple_fixture.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,8 @@
+"""
+This should fail:
+"""
+import grok
+
+class MultipleNames(grok.View):
+    grok.name('mammoth')
+    grok.name('bear')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/namemultiple_fixture.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nameunicode.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nameunicode.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nameunicode.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+# -*- coding: latin-1 -*-
+"""
+You can only pass unicode to `grok.name`:
+
+  >>> pass_unicode()
+  >>> pass_encodedstring()
+  Traceback (most recent call last):
+    ...
+  GrokImportError: You can only pass unicode or ASCII to grok.name.
+  >>> pass_object()
+  Traceback (most recent call last):
+    ...
+  GrokImportError: You can only pass unicode or ASCII to grok.name.
+
+"""
+import grok
+
+def pass_unicode():
+    class View(object):
+        grok.name(u'name')
+
+def pass_encodedstring():
+    class View(object):
+        grok.name("ölkj")
+
+def pass_object():
+    class View(object):
+        grok.name(object())


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nameunicode.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nomodulename.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nomodulename.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nomodulename.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,9 @@
+"""
+You can't call grok.name on a module:
+
+  >>> import grok.tests.view.nomodulename_fixture
+  Traceback (most recent call last):
+    ...
+  GrokImportError: grok.name can only be used on class level.
+
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nomodulename.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nomodulename_fixture.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nomodulename_fixture.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nomodulename_fixture.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+"""
+This should fail:
+"""
+import grok
+grok.name('viewname')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/nomodulename_fixture.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/notemplateorrender.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/notemplateorrender.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/notemplateorrender.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,18 @@
+"""
+Views either need an associated template or a ``render`` method:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: View <class 'grok.tests.view.notemplateorrender.CavePainting'>
+  has no associated template or 'render' method.
+
+"""
+
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class CavePainting(grok.View):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/notemplateorrender.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/template.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/template.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/template.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,41 @@
+"""
+
+  >>> grok.grok(__name__)
+
+View with an associated PageTemplate that is referred to using
+``grok.template``:
+
+  >>> manfred = Mammoth()
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+  >>> view = component.getMultiAdapter((manfred, request), name='painting')
+  >>> print view()
+  <html><body><h1>GROK PAINT MAMMOTH!</h1></body></html>
+
+``grok.name`` and ``grok.template`` can be combined:
+
+  >>> view = component.getMultiAdapter((manfred, request), name='meal')
+  >>> print view()
+  <html><body><h1>GROK EAT MAMMOTH!</h1></body></html>
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class Painting(grok.View):
+    grok.template('cavepainting')
+
+cavepainting = grok.PageTemplate("""\
+<html><body><h1>GROK PAINT MAMMOTH!</h1></body></html>
+""")
+
+class Food(grok.View):
+    grok.template('food_template')
+    grok.name('meal')
+
+food_template = grok.PageTemplate("""\
+<html><body><h1>GROK EAT MAMMOTH!</h1></body></html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/template.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatedirectory.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatedirectory.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatedirectory.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,27 @@
+"""
+You can explicitly specify the template directory using grok.templatedir on module level:
+
+  >>> grok.grok(__name__)
+
+  >>> manfred = Mammoth()
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+  >>> view = component.getMultiAdapter((manfred, request), name='food')
+  >>> print view()
+  <html>
+  <body>
+  ME GROK EAT MAMMOTH!
+  </body>
+  </html>
+
+"""
+import grok
+
+grok.templatedir('templatedirectoryname')
+
+class Mammoth(grok.Model):
+    pass
+
+class Food(grok.View):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatedirectory.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatedirectoryname/food.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatedirectoryname/food.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatedirectoryname/food.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+ME GROK EAT MAMMOTH!
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatefile.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatefile.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatefile.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,31 @@
+"""
+
+  >>> grok.grok(__name__)
+
+View with an associated PageTemplate that is referred to using
+``grok.template``:
+
+  >>> manfred = Mammoth()
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+  >>> view = component.getMultiAdapter((manfred, request), name='food')
+  >>> print view()
+  <html>
+  <body>
+  ME GROK EAT MAMMOTH!
+  </body>
+  </html>
+
+"""
+import grok
+import os.path
+
+class Mammoth(grok.Model):
+    pass
+
+class Food(grok.View):
+    pass
+
+food = grok.PageTemplateFile(os.path.join('templatedirectoryname',
+                                          'food.pt'))


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatefile.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatenotfound.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatenotfound.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatenotfound.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,20 @@
+"""
+This should fail because ``grok.template`` points to a non-existing
+template:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: View <class 'grok.tests.view.templatenotfound.Painting'>
+  has no associated template or 'render' method.
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class Painting(grok.View):
+    grok.template('cavepainting')
+
+# no cavepainting template here


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatenotfound.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatereload.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatereload.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatereload.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,39 @@
+"""
+Filesystem-based templates, once grokked, can be changed.  The change
+will automatically be picked up, reloading Zope is not necessary.
+
+  >>> grok.grok(__name__)
+  >>> from zope.component import getMultiAdapter
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> view = getMultiAdapter((Mammoth(), request), name='index')
+  >>> print view()
+  before
+
+Now we change the file:
+
+  >>> import os.path
+  >>> here = os.path.dirname(__file__)
+  >>> template_file = os.path.join(here, 'templatereload_templates', 'index.pt')
+  >>> template = open(template_file, 'w')
+  >>> template.write('after')
+  >>> template.close()
+
+and find that the output of the view has changed as well:
+
+  >>> print view()
+  after
+
+At last, we should change everything back to normal:
+
+  >>> template = open(template_file, 'w')
+  >>> template.write('before')
+  >>> template.close()
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class Index(grok.View):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatereload.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatereload_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatereload_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/templatereload_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+before
\ No newline at end of file

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/twoviewsusetemplate.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/twoviewsusetemplate.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/twoviewsusetemplate.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,61 @@
+"""
+A template can be used by multiple views at the same time:
+
+  >>> grok.grok(__name__)
+
+  >>> manfred = Mammoth()
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+
+  >>> view = component.getMultiAdapter((manfred, request), name='a')
+  >>> print view()
+  View A
+
+  >>> view = component.getMultiAdapter((manfred, request), name='b')
+  >>> print view()
+  View A
+
+It also works if templates are both associated explicitly:
+
+  >>> view = component.getMultiAdapter((manfred, request), name='c')
+  >>> print view()
+  Template
+
+  >>> view = component.getMultiAdapter((manfred, request), name='d')
+  >>> print view()
+  Template
+
+Because the template is associated, we do not expect it to be
+registered as its own view:
+
+  >>> view = component.getMultiAdapter((manfred, request), name='templ')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError:
+  ((<grok.tests.view.twoviewsusetemplate.Mammoth object at 0x...>,
+  <zope.publisher.browser.TestRequest instance URL=http://127.0.0.1>),
+  <InterfaceClass zope.interface.Interface>, 'templ')
+
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class A(grok.View):
+    pass
+
+a = grok.PageTemplate("View A")
+
+class B(grok.View):
+    grok.template('a')
+
+class C(grok.View):
+    grok.template('templ')
+
+class D(grok.View):
+    grok.template('templ')
+
+templ = grok.PageTemplate('Template')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/twoviewsusetemplate.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/unassociated.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/unassociated.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/unassociated.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,17 @@
+"""
+Templates that are not associated with a view class will provoke an
+error:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+  ...
+  GrokError: 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).
+
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/unassociated.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/unassociated_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/unassociated_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/unassociated_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+This template does not have an associated view class (in other words,
+there's no grok.tests.view.unassociated.Index class), therefore it
+provokes a GrokError.

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/update.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/update.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/update.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,46 @@
+"""
+Before a view is rendered, the update() method is executed. It can be
+used e. g. to execute side effects or set up data for use in the
+template.
+
+  >>> grok.grok(__name__)
+
+We need to set up a default ITraversable adapter so that TALES
+expressions can resolve paths:
+
+  >>> from zope import component
+  >>> from zope.traversing.adapters import DefaultTraversable
+  >>> component.provideAdapter(DefaultTraversable, (None,))
+
+  >>> manfred = Mammoth()
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> view = component.getMultiAdapter((manfred, request), name='cavepainting')
+  >>> print view()
+  <html>
+  <body>
+  <h1>red</h1>
+  <h1>red</h1>
+  </body>
+  </html>
+  
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class CavePainting(grok.View):
+    def update(self):
+        self.color = "red"
+
+
+cavepainting = grok.PageTemplate("""\
+<html>
+<body>
+<h1 tal:content="view/color"/>
+<h1 tal:content="python: view.color"/>
+</body>
+</html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/update.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/update_redirect.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/update_redirect.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/update_redirect.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,36 @@
+"""
+When a view's update() method redirects somewhere else, the template
+is not executed subsequently.
+
+  >>> grok.grok(__name__)
+
+  >>> manfred = Mammoth()
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope.component import getMultiAdapter
+  >>> view = getMultiAdapter((manfred, request), name='cavepainting')
+  >>> print view()
+  None
+  >>> print request.response.getStatus()
+  302
+  >>> print request.response.getHeader('Location')
+  somewhere-else
+
+"""
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class CavePainting(grok.View):
+    def update(self):
+        self.request.response.redirect('somewhere-else')
+
+
+cavepainting = grok.PageTemplate("""\
+<html>
+<body>
+<h1 tal:content="this-is-an-error" />
+</body>
+</html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/update_redirect.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/view.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/view/view.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/view/view.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,50 @@
+"""
+
+  >>> grok.grok(__name__)
+
+We should find the ``cavepainting`` view for a mammoth:
+
+  >>> manfred = Mammoth()
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+  >>> view = component.getMultiAdapter((manfred, request), name='cavepainting')
+  >>> view()
+  'A cave painting of a mammoth'
+
+  >>> view.context is manfred
+  True
+  >>> view.request is request
+  True
+
+Look up a view with a name explicitly set with ``grok.name``:
+
+  >>> view = component.getMultiAdapter((manfred, request), name='meal')
+  >>> view()
+  'Mammoth burger'
+
+There's no view 'food':
+
+  >>> view = component.getMultiAdapter((manfred, request), name='food')
+  Traceback (most recent call last):
+    ...
+  ComponentLookupError: ((<grok.tests.view.view.Mammoth object at 0x...>, <zope.publisher.browser.TestRequest instance URL=http://127.0.0.1>), <InterfaceClass zope.interface.Interface>, 'food')
+
+"""
+
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class CavePainting(grok.View):
+
+    def render(self):
+        return 'A cave painting of a mammoth'
+
+class Food(grok.View):
+    """Grok says: ME NO SEE MAMMOTH, ME SEE MEAL!"""
+    grok.name('meal')
+
+    def render(self):
+        return 'Mammoth burger'


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/view/view.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/xmlrpc/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/xmlrpc/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/xmlrpc/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/xmlrpc/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/xmlrpc/nocontext.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/xmlrpc/nocontext.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/xmlrpc/nocontext.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,16 @@
+"""
+
+Context-determination follows the same rules as for adapters. We just check
+whether it's hooked up at all:
+
+  >>> grok.grok(__name__)
+  Traceback (most recent call last):
+    ...
+  GrokError: No module-level context for
+  <class 'grok.tests.xmlrpc.nocontext.HomeRPC'>, please use grok.context.
+
+"""
+import grok
+
+class HomeRPC(grok.XMLRPC):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/xmlrpc/nocontext.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveerror.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveerror.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveerror.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,25 @@
+"""
+When a GrokImportError occurs, ZCML will give the proper stack trace:
+
+  >>> import grok
+  >>> from zope.configuration import xmlconfig
+  >>> context = xmlconfig.file('meta.zcml', grok)
+
+  >>> ignored = xmlconfig.string('''
+  ... <configure
+  ...     xmlns="http://namespaces.zope.org/zope"
+  ...     xmlns:grok="http://namespaces.zope.org/grok"
+  ...     >
+  ...     <grok:grok package="grok.tests.zcml.directiveerror"/>
+  ... </configure>''', context=context)
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "...", line ...
+  GrokError: No module-level context for
+  <class 'grok.tests.zcml.directiveerror.CavePainting'>, please use grok.context.
+
+"""
+import grok
+
+class CavePainting(grok.View):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveerror.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveimporterror.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveimporterror.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveimporterror.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,19 @@
+"""
+When a GrokImportError occurs, ZCML will give the proper stack trace:
+
+  >>> import grok
+  >>> from zope.configuration import xmlconfig
+  >>> context = xmlconfig.file('meta.zcml', grok)
+
+  >>> ignored = xmlconfig.string('''
+  ... <configure
+  ...     xmlns="http://namespaces.zope.org/zope"
+  ...     xmlns:grok="http://namespaces.zope.org/grok"
+  ...     >
+  ...     <grok:grok package="grok.tests.zcml.directiveimporterror_fixture"/>
+  ... </configure>''', context=context)
+  Traceback (most recent call last):
+    ...
+  ZopeXMLConfigurationError: File "...", line ...
+  GrokImportError: grok.template can only be used on class level.
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveimporterror.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveimporterror_fixture.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveimporterror_fixture.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveimporterror_fixture.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+"""
+This will raise a GrokImportError
+"""
+import grok
+grok.template('invalid')


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directiveimporterror_fixture.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directivemodule.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directivemodule.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directivemodule.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,28 @@
+"""
+  >>> import grok
+  >>> from zope.configuration import xmlconfig
+  >>> context = xmlconfig.file('meta.zcml', grok)
+
+  >>> ignored = xmlconfig.string('''
+  ... <configure
+  ...     xmlns="http://namespaces.zope.org/zope"
+  ...     xmlns:grok="http://namespaces.zope.org/grok"
+  ...     >
+  ...     <grok:grok package="grok.tests.zcml.stoneage.cave"/>
+  ... </configure>''', context=context)
+
+  >>> from grok.tests.zcml.stoneage.cave import Cave
+  >>> cave = Cave()
+  
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+
+  >>> view = component.getMultiAdapter((cave, request), name='index')
+  >>> print view()
+  <html>
+  <body>
+  <h1>A comfy cave</h1>
+  </body>
+  </html>
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directivemodule.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directivepackage.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directivepackage.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directivepackage.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,38 @@
+"""
+  >>> import grok
+  >>> from zope.configuration import xmlconfig
+  >>> context = xmlconfig.file('meta.zcml', grok)
+
+  >>> ignored = xmlconfig.string('''
+  ... <configure
+  ...     xmlns="http://namespaces.zope.org/zope"
+  ...     xmlns:grok="http://namespaces.zope.org/grok"
+  ...     >
+  ...     <grok:grok package="grok.tests.zcml.stoneage"/>
+  ... </configure>''', context=context)
+
+  >>> from grok.tests.zcml.stoneage.cave import Cave
+  >>> from grok.tests.zcml.stoneage.hunt.mammoth import Mammoth
+  >>> manfred = Mammoth()
+  >>> cave = Cave()
+  
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> from zope import component
+
+  >>> view = component.getMultiAdapter((cave, request), name='index')
+  >>> print view()
+  <html>
+  <body>
+  <h1>A comfy cave</h1>
+  </body>
+  </html>
+  
+  >>> view = component.getMultiAdapter((manfred, request), name='index')
+  >>> print view()
+  <html>
+  <body>
+  <h1>ME GROK HUNT MAMMOTH!</h1>
+  </body>
+  </html>
+"""


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/directivepackage.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,3 @@
+# this is a package
+
+


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/cave.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/cave.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/cave.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,15 @@
+import grok
+
+class Cave(grok.Model):
+    pass
+
+class Index(grok.View):
+    pass
+
+index = grok.PageTemplate("""\
+<html>
+<body>
+<h1>A comfy cave</h1>
+</body>
+</html>
+""")


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/cave.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/mammoth.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/mammoth.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/mammoth.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,7 @@
+import grok
+
+class Mammoth(grok.Model):
+    pass
+
+class Index(grok.View):
+    pass


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/mammoth.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/mammoth_templates/index.pt
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/mammoth_templates/index.pt	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/hunt/mammoth_templates/index.pt	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,5 @@
+<html>
+<body>
+<h1>ME GROK HUNT MAMMOTH!</h1>
+</body>
+</html>

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/notpackage/dummy.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/notpackage/dummy.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/notpackage/dummy.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# foo


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/notpackage/dummy.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/painting/__init__.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/painting/__init__.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/painting/__init__.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1 @@
+# this is a package


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/tests/zcml/stoneage/painting/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/util.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/util.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/util.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,86 @@
+##############################################################################
+#
+# Copyright (c) 2006-2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Grok utility functions.
+"""
+
+import urllib
+
+from zope import component
+from zope.traversing.browser.interfaces import IAbsoluteURL
+from zope.traversing.browser.absoluteurl import _safe as SAFE_URL_CHARACTERS
+
+from zope.security.checker import NamesChecker, defineChecker
+from zope.security.interfaces import IPermission
+
+from martian.error import GrokError, GrokImportError
+from martian.util import class_annotation
+
+def check_adapts(class_):
+    if component.adaptedBy(class_) is None:
+        raise GrokError("%r must specify which contexts it adapts "
+                        "(use grok.adapts to specify)."
+                        % class_, class_)
+
+def make_checker(factory, view_factory, permission):
+    """Make a checker for a view_factory associated with factory.
+
+    These could be one and the same for normal views, or different
+    in case we make method-based views such as for JSON and XMLRPC.
+    """
+    if permission is not None:
+        check_permission(factory, permission)
+    if permission is None or permission == 'zope.Public':
+        checker = NamesChecker(['__call__'])
+    else:
+        checker = NamesChecker(['__call__'], permission)
+    defineChecker(view_factory, checker)
+
+def check_permission(factory, permission):
+    """Check whether a permission is defined.
+
+    If not, raise error for factory.
+    """
+    if component.queryUtility(IPermission,
+                              name=permission) is None:
+       raise GrokError('Undefined permission %r in %r. Use '
+                       'grok.define_permission first.'
+                       % (permission, factory), factory)
+
+def get_default_permission(factory):
+    """Determine the default permission for a view.
+    
+    There can be only 0 or 1 default permission.
+    """
+    permissions = class_annotation(factory, 'grok.require', [])
+    if not permissions:
+        return None
+    if len(permissions) > 1:
+        raise GrokError('grok.require was called multiple times in '
+                        '%r. It may only be set once for a class.'
+                        % factory, factory)
+
+    result = permissions[0]
+    check_permission(factory, result)
+    return result
+
+def url(request, obj, name=None):
+    """Given a request and an object, give the URL.
+
+    Optionally pass a third argument name which gets added to the URL.
+    """    
+    url = component.getMultiAdapter((obj, request), IAbsoluteURL)()
+    if name is None:
+        return url
+    return url + '/' + urllib.quote(name.encode('utf-8'),
+                                    SAFE_URL_CHARACTERS)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/util.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: grok/branches/darrylcousins-martian-layers/src/grok/zcml.py
===================================================================
--- grok/branches/darrylcousins-martian-layers/src/grok/zcml.py	                        (rev 0)
+++ grok/branches/darrylcousins-martian-layers/src/grok/zcml.py	2007-06-26 13:10:53 UTC (rev 77094)
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Grok ZCML-Directives
+"""
+from zope import interface
+import zope.configuration.fields
+import grok
+
+class IGrokDirective(interface.Interface):
+    """Grok a package or module.
+    """
+
+    package = zope.configuration.fields.GlobalObject(
+        title=u"Package",
+        description=u"The package or module to be analyzed by grok.",
+        required=False,
+        )
+
+def grokDirective(_context, package):
+    grok.grok(package.__name__)


Property changes on: grok/branches/darrylcousins-martian-layers/src/grok/zcml.py
___________________________________________________________________
Name: svn:keywords
   + Id



More information about the Checkins mailing list