[Zope3-checkins] SVN: Zope3/branches/srichter-blow-services/ Merged trunk to branch. I still ahve 4 ftests failing, but I suspect, it

Stephan Richter srichter at cosmos.phy.tufts.edu
Thu Feb 10 10:21:19 EST 2005


Log message for revision 29102:
  Merged trunk to branch. I still ahve 4 ftests failing, but I suspect, it 
  will be fixed once I merge the changes of the last three days (hopefully).
  
  

Changed:
  U   Zope3/branches/srichter-blow-services/doc/CHANGES.txt
  U   Zope3/branches/srichter-blow-services/doc/TODO.txt
  U   Zope3/branches/srichter-blow-services/ftesting.zcml
  A   Zope3/branches/srichter-blow-services/package-includes/authentication-configure.zcml
  D   Zope3/branches/srichter-blow-services/package-includes/pau-configure.zcml
  U   Zope3/branches/srichter-blow-services/sample_principals.zcml
  A   Zope3/branches/srichter-blow-services/securitypolicy-ftesting.zcml
  U   Zope3/branches/srichter-blow-services/src/bugtracker/configure.zcml
  _U  Zope3/branches/srichter-blow-services/src/zdaemon/
  _U  Zope3/branches/srichter-blow-services/src/zdaemon/tests/
  U   Zope3/branches/srichter-blow-services/src/zdaemon/tests/testzdrun.py
  U   Zope3/branches/srichter-blow-services/src/zdaemon/zdoptions.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/apidoc/browser/apidoc.css
  U   Zope3/branches/srichter-blow-services/src/zope/app/apidoc/browser/index.pt
  U   Zope3/branches/srichter-blow-services/src/zope/app/appsetup/configure.zcml
  A   Zope3/branches/srichter-blow-services/src/zope/app/authentication/
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/README.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/__init__.py
  UU  Zope3/branches/srichter-blow-services/src/zope/app/authentication/authentication.py
  UU  Zope3/branches/srichter-blow-services/src/zope/app/authentication/authenticationplugins.zcml
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/__init__.py
  UU  Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/configure.zcml
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/ftests.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/group_searching_with_empty_string.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/groupfolder.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/groupfolder.zcml
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/loginform.pt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/principalfolder.txt
  UU  Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/schemasearch.py
  UU  Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/schemasearch.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/special-groups.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/tests.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/browserplugins.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/challengeplugins.zcml
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/configure.zcml
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/extractionplugins.zcml
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/generic.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/groupfolder.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/groupfolder.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/groupfolder.zcml
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/httpplugins.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/idpicker.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/idpicker.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/interfaces.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/principalfolder.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/principalfolder.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/principalplugins.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/principalplugins.zcml
  _U  Zope3/branches/srichter-blow-services/src/zope/app/authentication/sql.py
  UU  Zope3/branches/srichter-blow-services/src/zope/app/authentication/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/broken/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/broken/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/catalog/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/catalog/interfaces.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/metaconfigure.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/metadirectives.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/registration.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/tests/adapter.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/tests/test_directives.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/container/browser/metaconfigure.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/container/browser/tests/test_directive.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/container/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/dublincore/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/error/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/event/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/add.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/boolwidgets.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/interfaces.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/metaconfigure.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/metadirectives.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/orderedSelectionList.pt
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/sequencewidget.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/form/browser/source.py
  UU  Zope3/branches/srichter-blow-services/src/zope/app/form/browser/source.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_add.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_checkboxwidget.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_displaywidget.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_intwidget.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_sequencewidget.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_textwidget.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/textwidgets.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/form/browser/widget.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/ftests/test_functional.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/generations/README.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/generations/browser/managers.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/generations/generations.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/generations/subscriber.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/generations/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/generations/utility.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/homefolder/README.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/i18n/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/i18n/translationdomain.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/interpreter/python.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/intid/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/introspector/introspector.pt
  U   Zope3/branches/srichter-blow-services/src/zope/app/locales/de/LC_MESSAGES/zope.mo
  U   Zope3/branches/srichter-blow-services/src/zope/app/locales/de/LC_MESSAGES/zope.po
  A   Zope3/branches/srichter-blow-services/src/zope/app/locking/
  _U  Zope3/branches/srichter-blow-services/src/zope/app/locking/README.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/locking/__init__.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/locking/adapter.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/locking/configure.zcml
  _U  Zope3/branches/srichter-blow-services/src/zope/app/locking/interfaces.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/locking/lockinfo.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/locking/storage.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/locking/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/mail/delivery.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/mail/metaconfigure.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/module/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/observable/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/pagelet/README.txt
  D   Zope3/branches/srichter-blow-services/src/zope/app/pau/
  U   Zope3/branches/srichter-blow-services/src/zope/app/pluggableauth/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/presentation/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/menu.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/tests/test_addMenuItem.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/tests/test_directives.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/viewmeta.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/publisher/xmlrpc/README.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/registration/registration.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/rotterdam/template.pt
  U   Zope3/branches/srichter-blow-services/src/zope/app/schema/metadirectives.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/browser/auth.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/browser/authutilitysearchview.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/browser/configure.zcml
  A   Zope3/branches/srichter-blow-services/src/zope/app/security/browser/loginlogout.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/browser/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/configure.zcml
  A   Zope3/branches/srichter-blow-services/src/zope/app/security/globalprincipals.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/interfaces.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/meta.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/metaconfigure.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/metadirectives.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/permission.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/principalregistry.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/tests/test_directives.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/browser/manage_access.pt
  U   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/browser/manage_roleform.pt
  U   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/role.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/functional.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/functional.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/zopepolicy.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/server/mkzopeinstance.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/server/tests/test_mkzopeinstance.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/session/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/session/design.txt
  D   Zope3/branches/srichter-blow-services/src/zope/app/table/
  U   Zope3/branches/srichter-blow-services/src/zope/app/testing/functional.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/testing/setup.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/traversing/namespace.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/undo/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/utility/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/versioncontrol/tests.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/wfmc/
  U   Zope3/branches/srichter-blow-services/src/zope/app/wfmc/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/wfmc/metaconfigure.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/wfmc/metadirectives.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/wfmc/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/workflow/stateful/configure.zcml
  A   Zope3/branches/srichter-blow-services/src/zope/bforest/
  _U  Zope3/branches/srichter-blow-services/src/zope/bforest/__init__.py
  _U  Zope3/branches/srichter-blow-services/src/zope/bforest/bforest.py
  _U  Zope3/branches/srichter-blow-services/src/zope/bforest/bforest.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/bforest/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/README.txt
  U   Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/property.py
  A   Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/property.txt
  D   Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/tests/
  A   Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/configuration/tests/test_config.py
  U   Zope3/branches/srichter-blow-services/src/zope/interface/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/interface/declarations.py
  U   Zope3/branches/srichter-blow-services/src/zope/interface/interfaces.py
  U   Zope3/branches/srichter-blow-services/src/zope/schema/_bootstrapfields.py
  U   Zope3/branches/srichter-blow-services/src/zope/schema/_field.py
  U   Zope3/branches/srichter-blow-services/src/zope/security/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/security/checker.py
  U   Zope3/branches/srichter-blow-services/src/zope/security/interfaces.py
  U   Zope3/branches/srichter-blow-services/src/zope/security/tests/test_checker.py
  U   Zope3/branches/srichter-blow-services/src/zope/structuredtext/__init__.py
  A   Zope3/branches/srichter-blow-services/src/zope/testing/module.py
  U   Zope3/branches/srichter-blow-services/src/zope/thread/__init__.py
  A   Zope3/branches/srichter-blow-services/src/zope/wfmc/
  U   Zope3/branches/srichter-blow-services/src/zope/wfmc/tests.py
  U   Zope3/branches/srichter-blow-services/src/zwiki/configure.zcml
  U   Zope3/branches/srichter-blow-services/zopeskel/bin/test.in
  U   Zope3/branches/srichter-blow-services/zopeskel/etc/overrides_ftesting.zcml
  U   Zope3/branches/srichter-blow-services/zopeskel/etc/principals.zcml.in

-=-
Modified: Zope3/branches/srichter-blow-services/doc/CHANGES.txt
===================================================================
--- Zope3/branches/srichter-blow-services/doc/CHANGES.txt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/doc/CHANGES.txt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -14,11 +14,57 @@
         `zope.deprecation`. It allows one to deprecate methods and properties
         in classes as well as any name in a module.
 
+      - The browser:containerViews directive provides an optional layer
+        attribute.
+
+      - Groups for unauthenticated users, authenticated users, and
+        everybody can now be defined in ZCML.
+
+      - A handler attribute is now used in subscriber directives for
+        event subscribers that don't create objects, which is the case
+        for most subscribers.  Using the factory attribute without a
+        provides attribute to register a handler is deprecated.
+
+      - Added the function zope.component.adapts for declaring interfaces
+        adapted by classes. This is similar to zope.interface.implements in
+        that it puts a marker on the class that has a significant meaning in
+        the component architecture machinery.
+
+      - It is no longer necessary to supply a for attribute in adapter
+        directives if the factory declares the interfaces or classes that it
+        adapts using zope.component.adapts.
+
+      - It is no longer necessary to specify a provides attribute in
+        an adapter or utility directive if the factory/component
+        implements/provides a single interface.
+
+      - Added `zope.security.canAccess` and `zope.security.canWrite`
+        convenience methods.  Often code wants to check if a certain option is
+        open to a user before presenting it.  If the code relies on a certain
+        permission, the Zope 3 goal of keeping knowledge of security
+        assertions out of the code and only in configuration is broken.
+        Instead, ask if the current intreaction canAccess or canWrite some
+        pertinent aspect of the object.  canAccess is used for both read
+        access on an attribute and call access to methods.
+
+      - Added lazy properties. (See zope/cachedescriptors/README.txt)
+
       - Added new `getNextUtility()`, `queryNextUtility()`, and
         `testingNextUtility()` functions to make it easier to find and test
         for utilities in higher-up sites. These mimic their service-based
         equivalents.
 
+      - Added a simplified Python API for registering global utilities
+        and adapters.
+
+      - Added initial indexing and cataloging support
+
+      - Added an integer-id facility for assigning integer identifiers
+        to objects.  In Zope 2, this functionality is internal to
+        catalogs. By separating id management out, multiple catalogs
+        and indexing structures can share the same id scheme, allowing
+        cross-catalog joins and other sorts of aggregated analyses.
+
       - Added `getInfo(generation)` method to `zope.app.generations`'s
         `ISchemaManager`. It will return some information about the evolver
         that brings the database to the specified generation. This way we can
@@ -36,8 +82,8 @@
         extend another macro, which is particularly useful for writing
         a skin that customizes another skin.
 
-      - Added pagelet concept. Pagelets are responsible for a piece 
-        of content in a view. They can be used to render additionaly 
+      - Added pagelet concept. Pagelets are responsible for a piece
+        of content in a view. They can be used to render additionaly
         provided information into a pagetemplate.
 
         + Added tales expression 'pagelet'
@@ -45,7 +91,7 @@
         + Added tales expression 'pagelets'
 
         + Added tales expression 'pagedata'
-        
+
       - Added pagelet chooser for store pagelet name in the annotation
         of a object.
 
@@ -78,14 +124,14 @@
 
         The directive now also makes sure that the class implements the
         `IPersistent` and `ILocation` interfaces; without those a class cannot
-        be a local utility. This addresses issue 297.  
+        be a local utility. This addresses issue 297.
 
       - The `Attribute` and `Method` class of the `zope.interface` have now a
         new public `interface` attribute that stores the interface they are
-        defined in.  
+        defined in.
 
       - New Pluggable Authentication Service, which is similar in philosophy to
-        the Zope 2 PAS.  One of the main reasons for this is to support 
+        the Zope 2 PAS.  One of the main reasons for this is to support
         principal groups. The following features are available in the core:
 
         o Extraction Plugins: Basic HTTP Auth, Session
@@ -95,7 +141,7 @@
 
         o Authentication Plugins: Persistent (ZODB), SQL-based (LDAP is also
           available, but needs to be separately be downloaded)
-        
+
         o Principal Factory Plugins: Default factory
 
         o Principal Search Plugins: Persistent (ZODB), SQL-based
@@ -133,7 +179,7 @@
         templates are trusted, and database-based templates are
         untrusted.
 
-      - Implemented rdb:gadflyRoot directive.    
+      - Implemented rdb:gadflyRoot directive.
 
       - Schemas are now copied before they are appended to content type or
         instance. This should probably become a policy later.
@@ -159,7 +205,7 @@
         to strings (and string-like objects) from within ZPT, e.g:
 
         tal:attributes="href string:login.html?nextURL=${request/URL/url:quote}
-        
+
         Other functions available are quote_plus, unquote, unquote_plus.
 
       - Added basic cataloging functionality.
@@ -218,8 +264,9 @@
         deprecation of all view-related API functions. One should use the
         adapter API functions instead.
 
-      - The `pluggableauth` package has been deprecated. The `pas` module
-        provides a much more modular approach with many more capabilities.
+      - The `pluggableauth` package has been deprecated. The `authentication`
+        module provides a much more modular approach with many more
+        capabilities.
 
       - Removed special `DomainRegistration` now that we have events for
         notification.
@@ -228,11 +275,16 @@
         notification. Also, renamed `PersistentRole` to `LocalRole`.
 
       - Refactored Registration component for local components
-      
+
         + Deprecated the `activated()` and `deactivated()` method. It is now
           replaced with the 'IRegistrationActivatedEvent' and
           'IRegistrationDectivatedEvent', respectively.
 
+        + Added an event dispatcher for component registrations to support
+          subscriptions for specific component types. E.g. one can declare a
+          subscriber for (IFoo, IRegistrationActivatedEvent) to be notified
+          when IFoo component registrations are activated.
+
         + Restructured registration framework to use direct references rather
           than paths.
 
@@ -244,18 +296,18 @@
         - Other traversal components raise TraversalError
 
         - getPrincipal of IAuthenticationService now raises
-          PrincipalLookupError. 
+          PrincipalLookupError.
 
       - Removed Browser Menu Service and implemented menus as subscriber
         adapters. Menu Item Types (in other words, menus) are now utilities
-        that provide `IMenuItemType`. 
+        that provide `IMenuItemType`.
 
         + Completes http://dev.zope.org/Zope3/AdaptersForMenuItems. New
           features such as sub-menus, icons, disabled entries and so on were
           not well defined and should be reconsidered in a different proposal.
 
         + Backward-compatibility of the existing `browser` directives was
-          ensured. 
+          ensured.
 
         + If you have a directive that accepts a menu as attribute, it now
           needs to be a `MenuField`, so that it is correctly resolved to a menu
@@ -266,26 +318,26 @@
           instead of having the machinery create one for you.
 
         + The two API methods `getMenu()` and `getFirstItemOfMenu()` of the
-          Browser Menu Service are now available as functions in 
+          Browser Menu Service are now available as functions in
           `zope.app.publisher.browser.menu` having identical semantics.
 
         + Added `order` attribute to the menu item that declares the item's
           relative position. In general the menu items are always sorted from
           most to least specific, which is determined by the order of the
           implemented interfaces of the object. If ambiguities still exists,
-          the order and then the title of the menu item are taken account. 
+          the order and then the title of the menu item are taken account.
 
       - Removed Presentation Serivce and implemented views as adapters. This
         mainly means that layers and skins became adapters. Here are some
         other points:
-        
+
         + Completes http://dev.zope.org/Zope3/ImplementViewsAsAdapters.
 
         + Backward-compatibility of the Zope component API and the browser
           directives was ensured.
 
         + The `setPresentationSkin()` and `getPresentationSkin()` directives
-          of `IRequest` objects were removed. They were not used anywhere but 
+          of `IRequest` objects were removed. They were not used anywhere but
           testing anyways.
 
         + The default skin is now just an adapter from `IRequest` to
@@ -304,8 +356,25 @@
           to a request. This effectively replaces the `setPresentationSkin()`
           method.
 
+        + Created an explicit IDefaultLayer, which is, by default, added to
+          incoming browser requests. However, it is not added when an explicit
+          skin is specified. This allows developers to create skins that do
+          not include the default layer.
+
     Bug Fixes
 
+      - Partially fixed issue #306 (Problem 2: Browser page and view directive
+        cannot register serveral pages views within different layers for
+        the same for, menu and title attributes.)
+
+      - Fixed issue #353 (applySkin does not work in functional doctests).
+
+      - Fixed issue #293 (SequenceWidget and CustomWidgetFactory).
+
+      - TextWidgets set the value attribute to "value" when the field
+        has a missing value set and was not required and when there
+        was no input.
+
       - Fixed a bug in the adapter registry that would prevent `dict`-derived
         utilites from being retrieved correctly.
 
@@ -314,7 +383,7 @@
         contain any special character, except for the hostname and the port.
 
       - Fixed intid utility: Registration and unregistration of
-        local utitlity services, context aware registration of nested 
+        local utitlity services, context aware registration of nested
         components that may provide their own intids utiltities.
 
       - Fixed browser:defaultView metaconfigure: for_ passes a GlobalObject
@@ -323,7 +392,7 @@
       - Changed negotiator import with "INegotiator" utility lookup in
         default global "TranslationDomain". This makes it possible to
         use local INegotiator utilities with the standard translation
-        domain. 
+        domain.
 
       - contents.html no longer breaks when no IAdding is available.
 
@@ -334,7 +403,7 @@
       - NotFound pages and stattus codes are now returned only when
         something can't be found during publishing-path (e.g. URL)
         traversal. Traversal errors within application code are no
-        longer treated as "Not Found" errors. 
+        longer treated as "Not Found" errors.
 
       - Added missing modification events when add forms modified
         objects (assigned properties) after they were added.
@@ -353,7 +422,7 @@
 
       Jim Fulton, Fred Drake, Philipp von Weitershausen, Stephan Richter,
       Gustavo Niemeyer, Daniel Nouri, Volker Bachschneider, Roger Ineichen,
-      Shane Hathaway, Bjorn Tillenius
+      Shane Hathaway, Bjorn Tillenius, Garrett Smith
 
       Note: If you are not listed and contributed, please add yourself. This
       note will be deleted before the release.

Modified: Zope3/branches/srichter-blow-services/doc/TODO.txt
===================================================================
--- Zope3/branches/srichter-blow-services/doc/TODO.txt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/doc/TODO.txt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -36,25 +36,7 @@
   interfaces. This has been done for page directives but needs to be
   done for other adapter directives.
 
-- Add a handler attribute to the subscriber directive.  Deprecate use
-  of `factory` attribute without a `provides` attribute.  So, you can
-  have::
 
-    <subscriber handler=".myfunc" for="ISomeEvent" />
-
-  or::
-
-    <subscriber factory=".myclass" for="IFoo" provides="IBar" />
-
-  But not::
-
-    <subscriber factory=".myfunc" for="ISomeEvent" />
-
-  or::
-
-    <subscriber handler=".myclass" for="IFoo" provides="IBar" />
-
-
 Miscellaneous
 -------------
 
@@ -79,8 +61,6 @@
 
 * 288: IE xmltree.js line 225 error 
 
-* 293: SequenceWidget and CustomWidgetFactory 
-
 * 296: missing display widgets 
 
 * 298: Role/permission title and description should be messageids

Modified: Zope3/branches/srichter-blow-services/ftesting.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/ftesting.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/ftesting.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -13,6 +13,7 @@
   <include files="package-includes/*-ftesting.zcml" />
 
   <include file="securitypolicy.zcml" />
+  <include file="securitypolicy-ftesting.zcml" />
 
   <!-- Principals -->
 
@@ -20,6 +21,21 @@
       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"

Copied: Zope3/branches/srichter-blow-services/package-includes/authentication-configure.zcml (from rev 29088, Zope3/trunk/package-includes/authentication-configure.zcml)


Property changes on: Zope3/branches/srichter-blow-services/package-includes/authentication-configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Deleted: Zope3/branches/srichter-blow-services/package-includes/pau-configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/package-includes/pau-configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/package-includes/pau-configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -1 +0,0 @@
-<include package="zope.app.pau" />
\ No newline at end of file

Modified: Zope3/branches/srichter-blow-services/sample_principals.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/sample_principals.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/sample_principals.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -6,8 +6,24 @@
 
   <unauthenticatedPrincipal
     id="zope.anybody"
-    title="Unauthenticated User" />
+    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
     id="zope.sample_manager"
     title="Sample Manager"

Copied: Zope3/branches/srichter-blow-services/securitypolicy-ftesting.zcml (from rev 29088, Zope3/trunk/securitypolicy-ftesting.zcml)


Property changes on: Zope3/branches/srichter-blow-services/securitypolicy-ftesting.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: Zope3/branches/srichter-blow-services/src/bugtracker/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/bugtracker/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/bugtracker/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -372,7 +372,7 @@
 
   <!-- Register event listener for change mails -->
   <subscriber
-      factory=".mail.Mailer"
+      handler=".mail.Mailer"
       for="zope.app.event.interfaces.IObjectCreatedEvent
            zope.app.event.interfaces.IObjectModifiedEvent" />
 


Property changes on: Zope3/branches/srichter-blow-services/src/zdaemon
___________________________________________________________________
Name: svn:ignore
   + *so
*.pyc
build



Property changes on: Zope3/branches/srichter-blow-services/src/zdaemon/tests
___________________________________________________________________
Name: svn:ignore
   + *so
*.pyc
build


Modified: Zope3/branches/srichter-blow-services/src/zdaemon/tests/testzdrun.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zdaemon/tests/testzdrun.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zdaemon/tests/testzdrun.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -90,7 +90,7 @@
         ##os.system("PYTHONPATH=%s %s %s -s %s %s &" %
         ##    (self.ppath, self.python, self.zdrun, self.zdsock, args))
 
-    def run(self, args, cmdclass=None):
+    def _run(self, args, cmdclass=None):
         if type(args) is type(""):
             args = args.split()
         try:
@@ -102,7 +102,7 @@
         class MyCmd(zdctl.ZDCmd):
             def do_sproing(self, rest):
                 print rest
-        self.run("-p echo sproing expected", cmdclass=MyCmd)
+        self._run("-p echo sproing expected", cmdclass=MyCmd)
         self.expect = "expected\n"
 
     def testSystem(self):
@@ -110,27 +110,27 @@
         self.expect = ""
 
 ##     def testInvoke(self):
-##         self.run("echo -n")
+##         self._run("echo -n")
 ##         self.expect = ""
 
 ##     def testControl(self):
 ##         self.rundaemon(["sleep", "1000"])
 ##         time.sleep(1)
-##         self.run("stop")
+##         self._run("stop")
 ##         time.sleep(1)
-##         self.run("exit")
+##         self._run("exit")
 ##         self.expect = "Sent SIGTERM\nExiting now\n"
 
 ##     def testStop(self):
 ##         self.rundaemon([self.python, self.nokill])
 ##         time.sleep(1)
-##         self.run("stop")
+##         self._run("stop")
 ##         time.sleep(1)
-##         self.run("exit")
+##         self._run("exit")
 ##         self.expect = "Sent SIGTERM\nSent SIGTERM; will exit later\n"
 
     def testHelp(self):
-        self.run("-h")
+        self._run("-h")
         import __main__
         self.expect = __main__.__doc__
 
@@ -224,15 +224,24 @@
             sys.executable,
             [sys.executable, os.path.join(self.here, 'parent.py')]
             )
-        time.sleep(2) # race condition possible here
+        # Wait for it to start, but no longer than a minute.
+        deadline = time.time() + 60
+        is_started = False
+        while time.time() < deadline:
+             response = send_action('status\n', zdrun_socket)
+             if response is None:
+                 time.sleep(0.05)
+             else:
+                 is_started = True
+                 break
+        self.assert_(is_started, "spawned process failed to start in a minute")
+        # Kill it, and wait a little to ensure it's dead.
         os.kill(zdctlpid, signal.SIGINT)
-        try:
-            response = send_action('status\n', zdrun_socket) or ''
-        except socket.error, msg:
-            response = ''
-        params = response.split('\n')
-        self.assert_(len(params) > 1, repr(response))
-        # kill the process
+        time.sleep(0.25)
+        # Make sure the child is still responsive.
+        response = send_action('status\n', zdrun_socket)
+        self.assert_(response is not None and '\n' in response)
+        # Kill the process.
         send_action('exit\n', zdrun_socket)
 
     def testUmask(self):

Modified: Zope3/branches/srichter-blow-services/src/zdaemon/zdoptions.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zdaemon/zdoptions.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zdaemon/zdoptions.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -202,9 +202,17 @@
 
          # Provide dynamic default method arguments
         if args is None:
-            args = sys.argv[1:]
+            try:
+                args = sys.argv[1:]
+            except AttributeError:
+                args = ()
+
         if progname is None:
-            progname = sys.argv[0]
+            try:
+                progname = sys.argv[0]
+            except (AttributeError, IndexError):
+                progname = 'zope'
+
         if doc is None:
             import __main__
             doc = __main__.__doc__

Modified: Zope3/branches/srichter-blow-services/src/zope/app/apidoc/browser/apidoc.css
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/apidoc/browser/apidoc.css	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/apidoc/browser/apidoc.css	2005-02-10 15:21:18 UTC (rev 29102)
@@ -27,7 +27,6 @@
     padding: 2pt;
     margin-bottom: 3pt;
     background: #fffbbe;
-    width: 98%;
 }
 
 div.menu {

Modified: Zope3/branches/srichter-blow-services/src/zope/app/apidoc/browser/index.pt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/apidoc/browser/index.pt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/apidoc/browser/index.pt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -3,7 +3,7 @@
     <title i18n:translate="">Zope 3 API Documentation</title>
   </head>
   <frameset cols="20%, *">
-    <frameset rows="120, *"> 
+    <frameset rows="140, *"> 
       <frame name="modules" src="modulelist.html">
       <frame name="menu" src="menu.html">
     </frameset>

Modified: Zope3/branches/srichter-blow-services/src/zope/app/appsetup/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/appsetup/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/appsetup/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -1,7 +1,7 @@
 <configure xmlns="http://namespaces.zope.org/zope">
 
   <subscriber
-      factory=".bootstrap.bootStrapSubscriber"
+      handler=".bootstrap.bootStrapSubscriber"
       for="zope.app.appsetup.IDatabaseOpenedEvent"
       />
 

Copied: Zope3/branches/srichter-blow-services/src/zope/app/authentication (from rev 29088, Zope3/trunk/src/zope/app/authentication)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/authentication/authentication.py
===================================================================
--- Zope3/trunk/src/zope/app/authentication/authentication.py	2005-02-09 01:00:34 UTC (rev 29088)
+++ Zope3/branches/srichter-blow-services/src/zope/app/authentication/authentication.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -89,7 +89,8 @@
         id = id[len(self.prefix):]
 
         for searcher in self.searchers:
-            searcher = queryUtility(IPrincipalSearchPlugin, searcher)
+            searcher = queryUtility(IPrincipalSearchPlugin, searcher, 
+                                    context=self)
             if searcher is None:
                 continue
 
@@ -103,7 +104,10 @@
 
     def getQueriables(self):
         for searcher_id in self.searchers:
-            searcher = queryUtility(IPrincipalSearchPlugin, searcher_id)
+            # ensure with context=self that we call it in the context if
+            # we call it form a PrincipalSource vocabulary
+            searcher = queryUtility(IPrincipalSearchPlugin, searcher_id, 
+                                    context=self)
             yield searcher_id, searcher
         
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/authentication/authenticationplugins.zcml
===================================================================
--- Zope3/trunk/src/zope/app/authentication/authenticationplugins.zcml	2005-02-09 01:00:34 UTC (rev 29088)
+++ Zope3/branches/srichter-blow-services/src/zope/app/authentication/authenticationplugins.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -17,6 +17,10 @@
     <require
         permission="zope.ManageServices"
         interface="zope.app.container.interfaces.IContainer" />
+    
+    <require
+        permission="zope.ManageServices"
+        attributes="prefix" />
 
   </localUtility>
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/authentication/browser/configure.zcml	2005-02-09 01:00:34 UTC (rev 29088)
+++ Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -58,6 +58,14 @@
       index="zope.ManageServices"
       />
 
+  <schemadisplay
+      schema="..principalfolder.IInternalPrincipalContainer"
+      label="Principal Folder Prefix"
+      name="prefix.html"
+      fields="prefix"
+      permission="zope.ManageServices"
+      menu="zmi_views" title="Prefix" />
+
   <editform
       schema="..httpplugins.IHTTPBasicAuthRealm"
       label="Change Realm"

Modified: Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/schemasearch.py
===================================================================
--- Zope3/trunk/src/zope/app/authentication/browser/schemasearch.py	2005-02-09 01:00:34 UTC (rev 29088)
+++ Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/schemasearch.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -44,7 +44,25 @@
         html = []
         
         # add sub title for source search field
-        html.append('<h4 i18n:translate="">%s %s</h4>' % (sourcename, sourcepath))
+        html.append('<h4>%s</h4>' % sourcename)
+        
+        # start row for path display field
+        html.append('<div class="row">')
+        
+        # for each source add path of source
+        html.append('  <div class="label">')
+        label = _(u"Source path")
+        title = _(u"Path to the source utility")
+        html.append('    <label for="%s" title="%s">' % (sourcename, title))
+        html.append('      %s' % label)
+        html.append('    </label>')
+        html.append('  </div>')
+        html.append('  <div class="field">')
+        html.append('      %s' % sourcepath)
+        html.append('    </field>')
+        html.append('  </div>')
+        html.append('</div>')
+        
         # start row for search fields
         html.append('<div class="row">')
 
@@ -52,35 +70,34 @@
             widget = getattr(self, field_name+'_widget')
             
             # for each field add lable...
-            html.append('<div class="label">')
-            html.append('<label for="%s" title="%s">'
+            html.append('  <div class="label">')
+            html.append('    <label for="%s" title="%s">'
                         % (widget.name, widget.hint))
-            html.append(widget.label)
-            html.append('</label>')
-            html.append('</div>')
+            html.append('      %s' % widget.label)
+            html.append('    </label>')
+            html.append('  </div>')
             
             # ...and field widget
-            html.append('<div class="field">')
-            html.append(widget())
+            html.append('  <div class="field">')
+            html.append('    %s' % widget())
 
             if widget.error():
-                html.append('<div class="error">')
-                html.append(widget.error())
-                html.append('</div>')
-            html.append('</div>')
+                html.append('    <div class="error">')
+                html.append('      %s' % widget.error())
+                html.append('    </div>')
+            html.append('  </div>')
         # end row
         html.append('</div>')
 
         # add search button for search fields
         html.append('<div class="row">')
-        html.append('<div class="field">')
-        html.append('<input type="submit" name="%s" value="%s" />'
+        html.append('  <div class="field">')
+        html.append('    <input type="submit" name="%s" value="%s" />'
                      % (name+'.search',
                         translate(search_label, context=self.request)))
+        html.append('  </div>')
         html.append('</div>')
-        html.append('</div>')
 
-
         return '\n'.join(html)
 
     def results(self, name):

Modified: Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/schemasearch.txt
===================================================================
--- Zope3/trunk/src/zope/app/authentication/browser/schemasearch.txt	2005-02-09 01:00:34 UTC (rev 29088)
+++ Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/schemasearch.txt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -52,23 +52,34 @@
 This allows us to render a search form.
 
   >>> print view.render('test') # doctest: +NORMALIZE_WHITESPACE
-  <h4 i18n:translate="">searchplugin /searchplugin</h4>
+  <h4>searchplugin</h4>
   <div class="row">
-  <div class="label">
-  <label for="test.field.search" title="">
-  Search String
-  </label>
+    <div class="label">
+      <label for="searchplugin" title="Path to the source utility">
+        Source path
+      </label>
+    </div>
+    <div class="field">
+        /searchplugin
+      </field>
+    </div>
   </div>
-  <div class="field">
-  <input class="textType" id="test.field.search" name="test.field.search"
+  <div class="row">
+    <div class="label">
+      <label for="test.field.search" title="">
+        Search String
+      </label>
+    </div>
+    <div class="field">
+      <input class="textType" id="test.field.search" name="test.field.search"
          size="20" type="text" value=""  />
+    </div>
   </div>
-  </div>
   <div class="row">
-  <div class="field">
-  <input type="submit" name="test.search" value="Search" />
+    <div class="field">
+      <input type="submit" name="test.search" value="Search" />
+    </div>
   </div>
-  </div>
 
 If we ask for results:
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/special-groups.txt
===================================================================
--- Zope3/trunk/src/zope/app/authentication/browser/special-groups.txt	2005-02-09 01:00:34 UTC (rev 29088)
+++ Zope3/branches/srichter-blow-services/src/zope/app/authentication/browser/special-groups.txt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -21,19 +21,19 @@
   ... Authorization: Basic mgr:mgrpw
   ... Content-Type: multipart/form-data; boundary=---------------------------51955270618919134971413296540
   ... 
-  ... -----------------------------51955270618919134971413296540
-  ... Content-Disposition: form-data; name="field.prefix"
-  ... 
-  ... users.
-  ... -----------------------------51955270618919134971413296540
-  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
-  ... 
-  ... Add
-  ... -----------------------------51955270618919134971413296540
-  ... Content-Disposition: form-data; name="add_input_name"
-  ... 
-  ... 
-  ... -----------------------------51955270618919134971413296540--
+  ... -----------------------------51955270618919134971413296540
+  ... Content-Disposition: form-data; name="field.prefix"
+  ... 
+  ... users.
+  ... -----------------------------51955270618919134971413296540
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+  ... 
+  ... Add
+  ... -----------------------------51955270618919134971413296540
+  ... Content-Disposition: form-data; name="add_input_name"
+  ... 
+  ... 
+  ... -----------------------------51955270618919134971413296540--
   ... """)
   HTTP/1.1 303 See Other
   ...
@@ -45,379 +45,380 @@
   ... Authorization: Basic mgr:mgrpw
   ... Content-Type: multipart/form-data; boundary=---------------------------1211945862063657304996683149
   ... 
-  ... -----------------------------1211945862063657304996683149
-  ... Content-Disposition: form-data; name="field.name"
-  ... 
-  ... users
-  ... -----------------------------1211945862063657304996683149
-  ... Content-Disposition: form-data; name="field.interface"
-  ... 
-  ... zope.app.authentication.interfaces.ISearchableAuthenticationPlugin
-  ... -----------------------------1211945862063657304996683149
-  ... Content-Disposition: form-data; name="field.interface-empty-marker"
-  ... 
-  ... 1
-  ... -----------------------------1211945862063657304996683149
-  ... Content-Disposition: form-data; name="field.permission"
-  ... 
-  ... 
-  ... -----------------------------1211945862063657304996683149
-  ... Content-Disposition: form-data; name="field.permission-empty-marker"
-  ... 
-  ... 1
-  ... -----------------------------1211945862063657304996683149
-  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
-  ... 
-  ... Add
-  ... -----------------------------1211945862063657304996683149--
-  ... """)
-  HTTP/1.1 303 See Other
-  ...
-
-Add a principal to it:
-
-  >>> print http(r"""
-  ... POST /++etc++site/default/PrincipalFolder/+/AddPrincipalInformation.html%3D HTTP/1.1
-  ... Authorization: Basic mgr:mgrpw
-  ... Content-Type: multipart/form-data; boundary=---------------------------10033016405103631412002637985
+  ... -----------------------------1211945862063657304996683149
+  ... Content-Disposition: form-data; name="field.name"
   ... 
-  ... -----------------------------10033016405103631412002637985
-  ... Content-Disposition: form-data; name="field.login"
-  ... 
-  ... bob
-  ... -----------------------------10033016405103631412002637985
-  ... Content-Disposition: form-data; name="field.password"
-  ... 
-  ... 123
-  ... -----------------------------10033016405103631412002637985
-  ... Content-Disposition: form-data; name="field.title"
-  ... 
-  ... Bob
-  ... -----------------------------10033016405103631412002637985
-  ... Content-Disposition: form-data; name="field.description"
-  ... 
-  ... 
-  ... -----------------------------10033016405103631412002637985
-  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
-  ... 
-  ... Add
-  ... -----------------------------10033016405103631412002637985
-  ... Content-Disposition: form-data; name="add_input_name"
-  ... 
-  ... 
-  ... -----------------------------10033016405103631412002637985--
-  ... """)
-  HTTP/1.1 303 See Other
-  ...
-
-Create a pluggable-authentication utility:
-
-  >>> print http(r"""
-  ... POST /++etc++site/default/@@contents.html HTTP/1.1
-  ... Authorization: Basic mgr:mgrpw
-  ... Content-Type: application/x-www-form-urlencoded
+  ... users
+  ... -----------------------------1211945862063657304996683149
+  ... Content-Disposition: form-data; name="field.interface"
   ... 
-  ... type_name=BrowserAdd__zope.app.authentication.authentication.LocalPluggableAuthentication&new_value=""")
-  HTTP/1.1 303 See Other
-  ...
-
-and register it:
-
-  >>> print http(r"""
-  ... POST /++etc++site/default/LocalPluggableAuthentication/addRegistration.html HTTP/1.1
-  ... Authorization: Basic mgr:mgrpw
-  ... Content-Type: multipart/form-data; boundary=---------------------------2567744622114531019698320091
-  ... Referer: http://localhost:8081/++etc++site/default/LocalPluggableAuthentication/addRegistration.html
+  ... zope.app.authentication.interfaces.ISearchableAuthenticationPlugin
+  ... -----------------------------1211945862063657304996683149
+  ... Content-Disposition: form-data; name="field.interface-empty-marker"
   ... 
-  ... -----------------------------2567744622114531019698320091
-  ... Content-Disposition: form-data; name="field.name"
-  ... 
-  ... 
-  ... -----------------------------2567744622114531019698320091
-  ... Content-Disposition: form-data; name="field.interface"
-  ... 
-  ... zope.app.security.interfaces.IAuthentication
-  ... -----------------------------2567744622114531019698320091
-  ... Content-Disposition: form-data; name="field.interface-empty-marker"
-  ... 
-  ... 1
-  ... -----------------------------2567744622114531019698320091
-  ... Content-Disposition: form-data; name="field.permission"
-  ... 
-  ... 
-  ... -----------------------------2567744622114531019698320091
-  ... Content-Disposition: form-data; name="field.permission-empty-marker"
-  ... 
-  ... 1
-  ... -----------------------------2567744622114531019698320091
-  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
-  ... 
-  ... Add
-  ... -----------------------------2567744622114531019698320091--
-  ... """)
-  HTTP/1.1 303 See Other
-  ...
-
-and configure it:
-
-  >>> print http(r"""
-  ... POST /++etc++site/default/LocalPluggableAuthentication/@@edit.html HTTP/1.1
-  ... Authorization: Basic mgr:mgrpw
-  ... Content-Type: multipart/form-data; boundary=---------------------------12424310211503201098946683515
+  ... 1
+  ... -----------------------------1211945862063657304996683149
+  ... Content-Disposition: form-data; name="field.permission"
   ... 
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.extractors.to"
-  ... 
-  ... HTTP Basic
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.extractors-empty-marker"
-  ... 
-  ... 
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.authenticators.to"
-  ... 
-  ... users
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.authenticators-empty-marker"
-  ... 
-  ... 
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.challengers.to"
-  ... 
-  ... No Challenge if Authenticated
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.challengers.to"
-  ... 
-  ... Zope Realm HTTP Basic
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.challengers-empty-marker"
-  ... 
-  ... 
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.factories.to"
-  ... 
-  ... Default
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.factories-empty-marker"
-  ... 
-  ... 
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.searchers.to"
-  ... 
-  ... users
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.searchers-empty-marker"
-  ... 
-  ... 
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
-  ... 
-  ... Change
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.extractors"
-  ... 
-  ... HTTP Basic
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.authenticators"
-  ... 
-  ... users
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.challengers"
-  ... 
-  ... No Challenge if Authenticated
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.challengers"
-  ... 
-  ... Zope Realm HTTP Basic
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.factories"
-  ... 
-  ... Default
-  ... -----------------------------12424310211503201098946683515
-  ... Content-Disposition: form-data; name="field.searchers"
-  ... 
-  ... users
-  ... -----------------------------12424310211503201098946683515--
-  ... """)
-  HTTP/1.1 200 Ok
-  ...
-
-Normally, the anonymous role has view, we'll deny it:
-
-  >>> print http(r"""
-  ... POST /++etc++site/AllRolePermissions.html HTTP/1.1
-  ... Authorization: Basic mgr:mgrpw
-  ... Content-Type: application/x-www-form-urlencoded
   ... 
-  ... role_id=zope.Anonymous""" 
-  ... """&Deny%3Alist=zope.View""" 
-  ... """&Deny%3Alist=zope.app.dublincore.view""" 
-  ... """&SUBMIT_ROLE=Save+Changes""")
-  HTTP/1.1 200 Ok
-  ...
-
-Now, if we try to access the main page as an anonymous user, we'll be unauthorized:
-
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... """)
-  HTTP/1.1 401 Unauthorized
-  ...
-
-We'll even be unauthorized if we try to access it as bob:
-
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... Authorization: Basic bob:123
-  ... """)
-  HTTP/1.1 403 Forbidden
-  ...
-
-No, let's grant view to the authenticated group:
-
-  >>> print http(r"""
-  ... POST /@@grant.html HTTP/1.1
-  ... Authorization: Basic mgr:mgrpw
-  ... Content-Type: application/x-www-form-urlencoded
+  ... -----------------------------1211945862063657304996683149
+  ... Content-Disposition: form-data; name="field.permission-empty-marker"
   ... 
-  ... field.principal=em9wZS5BdXRoZW50aWNhdGVk&field.principal.displayed=y"""
-  ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.View=allow"""
-  ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.app.dublincore.view=allow"""
-  ... """&GRANT_SUBMIT=Change""")
-  HTTP/1.1 200 Ok
-  ...
-
-Now, with this, we can access the main page as bob, but not as an
-anonymous user:
-
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... Authorization: Basic bob:123
-  ... """)
-  HTTP/1.1 200 Ok
-  ...
-
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... """)
-  HTTP/1.1 401 Unauthorized
-  ...
-
-Now, we'll grant to unauthenticated:
-
-  >>> print http(r"""
-  ... POST /@@grant.html HTTP/1.1
-  ... Authorization: Basic mgr:mgrpw
-  ... Content-Type: application/x-www-form-urlencoded
-  ... Referer: http://localhost:8081/@@grant.html
+  ... 1
+  ... -----------------------------1211945862063657304996683149
+  ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
   ... 
-  ... field.principal=em9wZS5Bbnlib2R5"""
-  ... """&field.em9wZS5Bbnlib2R5.permission.zope.View=allow"""
-  ... """&field.em9wZS5Bbnlib2R5.permission.zope.app.dublincore.view=allow"""
-  ... """&GRANT_SUBMIT=Change""")
-  HTTP/1.1 200 Ok
-  ...
-
-With this, we can access the page as either bob or anonymous:
-
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... Authorization: Basic bob:123
+  ... Add
+  ... -----------------------------1211945862063657304996683149--
   ... """)
-  HTTP/1.1 200 Ok
+  HTTP/1.1 303 See Other
   ...
 
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... """)
-  HTTP/1.1 200 Ok
-  ...
+# Add a principal to it:
+# 
+#   >>> print http(r"""
+#   ... POST /++etc++site/default/PrincipalFolder/+/AddPrincipalInformation.html%3D HTTP/1.1
+#   ... Authorization: Basic mgr:mgrpw
+#   ... Content-Type: multipart/form-data; boundary=---------------------------10033016405103631412002637985
+#   ... 
+#   ... -----------------------------10033016405103631412002637985
+#   ... Content-Disposition: form-data; name="field.login"
+#   ... 
+#   ... bob
+#   ... -----------------------------10033016405103631412002637985
+#   ... Content-Disposition: form-data; name="field.password"
+#   ... 
+#   ... 123
+#   ... -----------------------------10033016405103631412002637985
+#   ... Content-Disposition: form-data; name="field.title"
+#   ... 
+#   ... Bob
+#   ... -----------------------------10033016405103631412002637985
+#   ... Content-Disposition: form-data; name="field.description"
+#   ... 
+#   ... 
+#   ... -----------------------------10033016405103631412002637985
+#   ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+#   ... 
+#   ... Add
+#   ... -----------------------------10033016405103631412002637985
+#   ... Content-Disposition: form-data; name="add_input_name"
+#   ... 
+#   ... 
+#   ... -----------------------------10033016405103631412002637985--
+#   ... """)
+#   HTTP/1.1 303 See Other
+#   ...
+# 
+# Create a pluggable-authentication utility:
+# 
+#   >>> print http(r"""
+#   ... POST /++etc++site/default/@@contents.html HTTP/1.1
+#   ... Authorization: Basic mgr:mgrpw
+#   ... Content-Type: application/x-www-form-urlencoded
+#   ... 
+#   ... type_name=BrowserAdd__zope.app.authentication.authentication.LocalPluggableAuthentication&new_value=""")
+#   HTTP/1.1 303 See Other
+#   ...
+# 
+# and register it:
+# 
+#   >>> print http(r"""
+#   ... POST /++etc++site/default/LocalPluggableAuthentication/addRegistration.html HTTP/1.1
+#   ... Authorization: Basic mgr:mgrpw
+#   ... Content-Type: multipart/form-data; boundary=---------------------------2567744622114531019698320091
+#   ... Referer: http://localhost:8081/++etc++site/default/LocalPluggableAuthentication/addRegistration.html
+#   ... 
+#   ... -----------------------------2567744622114531019698320091
+#   ... Content-Disposition: form-data; name="field.name"
+#   ... 
+#   ... 
+#   ... -----------------------------2567744622114531019698320091
+#   ... Content-Disposition: form-data; name="field.interface"
+#   ... 
+#   ... zope.app.security.interfaces.IAuthentication
+#   ... -----------------------------2567744622114531019698320091
+#   ... Content-Disposition: form-data; name="field.interface-empty-marker"
+#   ... 
+#   ... 1
+#   ... -----------------------------2567744622114531019698320091
+#   ... Content-Disposition: form-data; name="field.permission"
+#   ... 
+#   ... 
+#   ... -----------------------------2567744622114531019698320091
+#   ... Content-Disposition: form-data; name="field.permission-empty-marker"
+#   ... 
+#   ... 1
+#   ... -----------------------------2567744622114531019698320091
+#   ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+#   ... 
+#   ... Add
+#   ... -----------------------------2567744622114531019698320091--
+#   ... """)
+#   HTTP/1.1 303 See Other
+#   ...
+# 
+# and configure it:
+# 
+#   >>> print http(r"""
+#   ... POST /++etc++site/default/LocalPluggableAuthentication/@@edit.html HTTP/1.1
+#   ... Authorization: Basic mgr:mgrpw
+#   ... Content-Type: multipart/form-data; boundary=---------------------------12424310211503201098946683515
+#   ... 
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.extractors.to"
+#   ... 
+#   ... HTTP Basic
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.extractors-empty-marker"
+#   ... 
+#   ... 
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.authenticators.to"
+#   ... 
+#   ... users
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.authenticators-empty-marker"
+#   ... 
+#   ... 
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.challengers.to"
+#   ... 
+#   ... No Challenge if Authenticated
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.challengers.to"
+#   ... 
+#   ... Zope Realm HTTP Basic
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.challengers-empty-marker"
+#   ... 
+#   ... 
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.factories.to"
+#   ... 
+#   ... Default
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.factories-empty-marker"
+#   ... 
+#   ... 
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.searchers.to"
+#   ... 
+#   ... users
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.searchers-empty-marker"
+#   ... 
+#   ... 
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+#   ... 
+#   ... Change
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.extractors"
+#   ... 
+#   ... HTTP Basic
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.authenticators"
+#   ... 
+#   ... users
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.challengers"
+#   ... 
+#   ... No Challenge if Authenticated
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.challengers"
+#   ... 
+#   ... Zope Realm HTTP Basic
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.factories"
+#   ... 
+#   ... Default
+#   ... -----------------------------12424310211503201098946683515
+#   ... Content-Disposition: form-data; name="field.searchers"
+#   ... 
+#   ... users
+#   ... -----------------------------12424310211503201098946683515--
+#   ... """)
+#   HTTP/1.1 200 Ok
+#   ...
+# 
+# Normally, the anonymous role has view, we'll deny it:
+# 
+#   >>> print http(r"""
+#   ... POST /++etc++site/AllRolePermissions.html HTTP/1.1
+#   ... Authorization: Basic mgr:mgrpw
+#   ... Content-Type: application/x-www-form-urlencoded
+#   ... 
+#   ... role_id=zope.Anonymous""" 
+#   ... """&Deny%3Alist=zope.View""" 
+#   ... """&Deny%3Alist=zope.app.dublincore.view""" 
+#   ... """&SUBMIT_ROLE=Save+Changes""")
+#   HTTP/1.1 200 Ok
+#   ...
+# 
+# Now, if we try to access the main page as an anonymous user, we'll be
+# unauthorized:
+# 
+#   >>> print http(r"""
+#   ... GET / HTTP/1.1
+#   ... """)
+#   HTTP/1.1 401 Unauthorized
+#   ...
+# 
+# We'll even be unauthorized if we try to access it as bob:
+# 
+#   >>> print http(r"""
+#   ... GET / HTTP/1.1
+#   ... Authorization: Basic bob:123
+#   ... """)
+#   HTTP/1.1 403 Forbidden
+#   ...
+# 
+# No, let's grant view to the authenticated group:
+# 
+#   >>> print http(r"""
+#   ... POST /@@grant.html HTTP/1.1
+#   ... Authorization: Basic mgr:mgrpw
+#   ... Content-Type: application/x-www-form-urlencoded
+#   ... 
+#   ... field.principal=em9wZS5BdXRoZW50aWNhdGVk&field.principal.displayed=y"""
+#   ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.View=allow"""
+#   ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.app.dublincore.view=allow"""
+#   ... """&GRANT_SUBMIT=Change""")
+#   HTTP/1.1 200 Ok
+#   ...
+# 
+# Now, with this, we can access the main page as bob, but not as an
+# anonymous user:
+# 
+#   >>> print http(r"""
+#   ... GET / HTTP/1.1
+#   ... Authorization: Basic bob:123
+#   ... """)
+#   HTTP/1.1 200 Ok
+#   ...
+# 
+#   >>> print http(r"""
+#   ... GET / HTTP/1.1
+#   ... """)
+#   HTTP/1.1 401 Unauthorized
+#   ...
+# 
+# Now, we'll grant to unauthenticated:
+# 
+#   >>> print http(r"""
+#   ... POST /@@grant.html HTTP/1.1
+#   ... Authorization: Basic mgr:mgrpw
+#   ... Content-Type: application/x-www-form-urlencoded
+#   ... Referer: http://localhost:8081/@@grant.html
+#   ... 
+#   ... field.principal=em9wZS5Bbnlib2R5"""
+#   ... """&field.em9wZS5Bbnlib2R5.permission.zope.View=allow"""
+#   ... """&field.em9wZS5Bbnlib2R5.permission.zope.app.dublincore.view=allow"""
+#   ... """&GRANT_SUBMIT=Change""")
+#   HTTP/1.1 200 Ok
+#   ...
+# 
+# With this, we can access the page as either bob or anonymous:
+# 
+#   >>> print http(r"""
+#   ... GET / HTTP/1.1
+#   ... Authorization: Basic bob:123
+#   ... """)
+#   HTTP/1.1 200 Ok
+#   ...
+# 
+#   >>> print http(r"""
+#   ... GET / HTTP/1.1
+#   ... """)
+#   HTTP/1.1 200 Ok
+#   ...
+# 
+# Now, we'll remove the authenticated group grant:
+# 
+#   >>> print http(r"""
+#   ... POST /@@grant.html HTTP/1.1
+#   ... Authorization: Basic mgr:mgrpw
+#   ... Content-Type: application/x-www-form-urlencoded
+#   ... 
+#   ... field.principal=em9wZS5BdXRoZW50aWNhdGVk"""
+#   ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.View=unset"""
+#   ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.app.dublincore.view=unset"""
+#   ... """&GRANT_SUBMIT=Change""")
+#   HTTP/1.1 200 Ok
+#   ...
+# 
+# And anonymous people will be able to access the page, but bob won't be able to:
+# 
+#   >>> print http(r"""
+#   ... GET / HTTP/1.1
+#   ... Authorization: Basic bob:123
+#   ... """)
+#   HTTP/1.1 403 Forbidden
+#   ...
+# 
+#   >>> print http(r"""
+#   ... GET / HTTP/1.1
+#   ... """)
+#   HTTP/1.1 200 Ok
+#   ...
+# 
+# Now, we'll remove the unauthenticated group grant:
+# 
+#   >>> print http(r"""
+#   ... POST /@@grant.html HTTP/1.1
+#   ... Authorization: Basic mgr:mgrpw
+#   ... Content-Type: application/x-www-form-urlencoded
+#   ... Referer: http://localhost:8081/@@grant.html
+#   ... 
+#   ... field.principal=em9wZS5Bbnlib2R5"""
+#   ... """&field.em9wZS5Bbnlib2R5.permission.zope.View=unset"""
+#   ... """&field.em9wZS5Bbnlib2R5.permission.zope.app.dublincore.view=unset"""
+#   ... """&GRANT_SUBMIT=Change""")
+#   HTTP/1.1 200 Ok
+#   ...
+# 
+# and neither bob nor anonymous can access:
+# 
+#   >>> print http(r"""
+#   ... GET / HTTP/1.1
+#   ... Authorization: Basic bob:123
+#   ... """)
+#   HTTP/1.1 403 Forbidden
+#   ...
+# 
+#   >>> print http(r"""
+#   ... GET / HTTP/1.1
+#   ... """)
+#   HTTP/1.1 401 Unauthorized
+#   ...
+# 
+# Finally, we'll grant to everybody:
+# 
+#   >>> print http(r"""
+#   ... POST /@@grant.html HTTP/1.1
+#   ... Authorization: Basic mgr:mgrpw
+#   ... Content-Type: application/x-www-form-urlencoded
+#   ... 
+#   ... field.principal=em9wZS5FdmVyeWJvZHk_"""
+#   ... """&field.em9wZS5FdmVyeWJvZHk_.permission.zope.View=allow"""
+#   ... """&field.em9wZS5FdmVyeWJvZHk_.permission.zope.app.dublincore.view=allow"""
+#   ... """&GRANT_SUBMIT=Change""", handle_errors = False)
+#   HTTP/1.1 200 Ok
+#   ...
+# 
+# and both bob nor anonymous can access:
+# 
+#   >>> print http(r"""
+#   ... GET / HTTP/1.1
+#   ... Authorization: Basic bob:123
+#   ... """)
+#   HTTP/1.1 200 Ok
+#   ...
+# 
+#   >>> print http(r"""
+#   ... GET / HTTP/1.1
+#   ... """)
+#   HTTP/1.1 200 Ok
+#   ...
 
-Now, we'll remove the authenticated group grant:
-
-  >>> print http(r"""
-  ... POST /@@grant.html HTTP/1.1
-  ... Authorization: Basic mgr:mgrpw
-  ... Content-Type: application/x-www-form-urlencoded
-  ... 
-  ... field.principal=em9wZS5BdXRoZW50aWNhdGVk"""
-  ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.View=unset"""
-  ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.app.dublincore.view=unset"""
-  ... """&GRANT_SUBMIT=Change""")
-  HTTP/1.1 200 Ok
-  ...
-
-And anonymous people will be able to access the page, but bob won't be able to:
-
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... Authorization: Basic bob:123
-  ... """)
-  HTTP/1.1 403 Forbidden
-  ...
-
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... """)
-  HTTP/1.1 200 Ok
-  ...
-
-Now, we'll remove the unauthenticated group grant:
-
-  >>> print http(r"""
-  ... POST /@@grant.html HTTP/1.1
-  ... Authorization: Basic mgr:mgrpw
-  ... Content-Type: application/x-www-form-urlencoded
-  ... Referer: http://localhost:8081/@@grant.html
-  ... 
-  ... field.principal=em9wZS5Bbnlib2R5"""
-  ... """&field.em9wZS5Bbnlib2R5.permission.zope.View=unset"""
-  ... """&field.em9wZS5Bbnlib2R5.permission.zope.app.dublincore.view=unset"""
-  ... """&GRANT_SUBMIT=Change""")
-  HTTP/1.1 200 Ok
-  ...
-
-and neither bob nor anonymous can access:
-
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... Authorization: Basic bob:123
-  ... """)
-  HTTP/1.1 403 Forbidden
-  ...
-
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... """)
-  HTTP/1.1 401 Unauthorized
-  ...
-
-Finally, we'll grant to everybody:
-
-  >>> print http(r"""
-  ... POST /@@grant.html HTTP/1.1
-  ... Authorization: Basic mgr:mgrpw
-  ... Content-Type: application/x-www-form-urlencoded
-  ... 
-  ... field.principal=em9wZS5FdmVyeWJvZHk_"""
-  ... """&field.em9wZS5FdmVyeWJvZHk_.permission.zope.View=allow"""
-  ... """&field.em9wZS5FdmVyeWJvZHk_.permission.zope.app.dublincore.view=allow"""
-  ... """&GRANT_SUBMIT=Change""", handle_errors = False)
-  HTTP/1.1 200 Ok
-  ...
-
-and both bob nor anonymous can access:
-
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... Authorization: Basic bob:123
-  ... """)
-  HTTP/1.1 200 Ok
-  ...
-
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... """)
-  HTTP/1.1 200 Ok
-  ...
-

Modified: Zope3/branches/srichter-blow-services/src/zope/app/authentication/tests.py
===================================================================
--- Zope3/trunk/src/zope/app/authentication/tests.py	2005-02-09 01:00:34 UTC (rev 29088)
+++ Zope3/branches/srichter-blow-services/src/zope/app/authentication/tests.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -59,7 +59,13 @@
 def groupSetUp(test):
     placelesssetup.setUp()
 
+def searcheableSetUp(self):
+    placefulSetUp(site=True)
 
+def searcheableTearDown(self):
+    placefulTearDown()
+
+
 def test_suite():
     return unittest.TestSuite((
         doctest.DocTestSuite('zope.app.authentication.generic'),
@@ -71,8 +77,8 @@
                              setUp=formAuthSetUp,
                              tearDown=formAuthTearDown),
         doctest.DocFileSuite('README.txt',
-                             setUp=placelesssetup.setUp,
-                             tearDown=placelesssetup.tearDown,
+                             setUp=searcheableSetUp,
+                             tearDown=searcheableTearDown,
                              globs={'provideUtility': ztapi.provideUtility,
                                     'getEvents': getEvents,
                                     }),

Modified: Zope3/branches/srichter-blow-services/src/zope/app/broken/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/broken/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/broken/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -6,7 +6,7 @@
   </content>
 
   <subscriber
-      factory=".broken.installBroken"
+      handler=".broken.installBroken"
       for="zope.app.appsetup.IDatabaseOpenedEvent" 
       />
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/broken/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/broken/tests.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/broken/tests.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -71,8 +71,8 @@
       Traceback (most recent call last):
       ...
       BrokenModified: Can't modify broken objects
-    
 
+
     Cleanup:
 
       >>> import ZODB.broken

Modified: Zope3/branches/srichter-blow-services/src/zope/app/catalog/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/catalog/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/catalog/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -28,23 +28,23 @@
 </content>
 
 <subscriber
-    factory=".catalog.indexAdded"
+    handler=".catalog.indexAdded"
     for=".interfaces.ICatalogIndex
          zope.app.container.interfaces.IObjectAddedEvent"
     />
 
 <subscriber
-    factory=".catalog.indexDocSubscriber"
+    handler=".catalog.indexDocSubscriber"
     for="zope.app.intid.interfaces.IIntIdAddedEvent"
     />
 
 <subscriber
-    factory=".catalog.reindexDocSubscriber"
+    handler=".catalog.reindexDocSubscriber"
     for="zope.app.event.objectevent.IObjectModifiedEvent"
     />
 
 <subscriber
-    factory=".catalog.unindexDocSubscriber"
+    handler=".catalog.unindexDocSubscriber"
     for="zope.app.intid.interfaces.IIntIdRemovedEvent"
     />
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/catalog/interfaces.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/catalog/interfaces.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/catalog/interfaces.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -63,7 +63,7 @@
     interface = zope.schema.Choice(
         title=_(u"Interface"),
         description=_(u"Objects will be adapted to this interface"),
-        vocabulary=_("Interfaces"),
+        vocabulary="Interfaces",
         required=False,
         )
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -48,21 +48,27 @@
       />
 
   <subscriber
-      factory=".registration.ComponentRegistrationRemoveSubscriber"
       for=".interfaces.registration.IComponentRegistration
            zope.app.container.interfaces.IObjectRemovedEvent"
+      handler=".registration.ComponentRegistrationRemoveSubscriber"
       />
 
   <subscriber
       for=".interfaces.registration.IComponentRegistration
            zope.app.container.interfaces.IObjectAddedEvent"
-      factory=".registration.ComponentRegistrationAddSubscriber"
+      handler=".registration.ComponentRegistrationAddSubscriber"
       />
 
   <subscriber
+      for=".interfaces.registration.IComponentRegistration
+           .interfaces.registration.IRegistrationEvent"
+      handler=".registration.componentRegistrationEventNotify"
+      />
+
+  <subscriber
       for=".interfaces.registration.IRegisterable
            zope.app.container.interfaces.IObjectMovedEvent"
-      factory=".registration.RegisterableMoveSubscriber"
+      handler=".registration.RegisterableMoveSubscriber"
       />
 
 
@@ -132,18 +138,18 @@
 
   <subscriber
       for="zope.app.publication.interfaces.IBeforeTraverseEvent"
-      factory=".site.threadSiteSubscriber"
+      handler=".site.threadSiteSubscriber"
       />
 
   <subscriber
       for="zope.app.publication.interfaces.IEndRequestEvent"
-      factory=".site.clearThreadSiteSubscriber"
+      handler=".site.clearThreadSiteSubscriber"
       />
 
   <subscriber
       for=".interfaces.ISite
            zope.app.container.interfaces.IObjectMovedEvent"
-      factory=".site.changeSiteConfigurationAfterMove"
+      handler=".site.changeSiteConfigurationAfterMove"
       />
 
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/metaconfigure.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/metaconfigure.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/metaconfigure.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -19,6 +19,7 @@
 
 from zope.component.interfaces import IDefaultViewName, IFactory
 from zope.configuration.exceptions import ConfigurationError
+import zope.interface
 from zope.interface import Interface
 from zope.interface.interfaces import IInterface
 
@@ -57,8 +58,27 @@
 
     return ob
 
-def subscriber(_context, factory, for_, provides=None, permission=None,
-               trusted=False):
+_handler=handler
+def subscriber(_context, for_, factory=None, handler=None, provides=None,
+               permission=None, trusted=False):
+
+    if factory is None:
+        if handler is None:
+            raise TypeError("No factory or handler provides")
+        if provides is not None:
+            raise TypeError("Cannot use handler with provides")
+        factory = handler
+    else:
+        if handler is not None:
+            raise TypeError("Cannot use handler with factory")
+        if provides is None:
+            import warnings
+            warnings.warn(
+                "Use of factory without provides to indicate a handler "
+                "is deprecated and will change it's meaning in Zope X3.3. "
+                "Use the handler attribute instead.",
+                DeprecationWarning)
+    
     factory = [factory]
 
     if permission is not None:
@@ -88,7 +108,7 @@
 
     _context.action(
         discriminator = None,
-        callable = handler,
+        callable = _handler,
         args = ('subscribe',
                 for_, provides, factory),
         )
@@ -109,16 +129,31 @@
                 args = ('', iface)
                 )
 
-def adapter(_context, factory, provides, for_, permission=None, name='',
-            trusted=False):
-    if permission is not None:
-        if permission == PublicPermission:
-            permission = CheckerPublic
-        checker = InterfaceChecker(provides, permission)
-        factory.append(lambda c: proxify(c, checker))
+def adapter(_context, factory, provides=None, for_=None, permission=None,
+            name='', trusted=False):
 
+    if for_ is None:
+        if len(factory) == 1:
+            try:
+                for_ = factory[0].__component_adapts__
+            except AttributeError:
+                pass
+
+        if for_ is None:
+            raise TypeError("No for attribute was provided and can't "
+                            "determine what the factory adapts.")
+
     for_ = tuple(for_)
 
+    if provides is None:
+        if len(factory) == 1:
+            p = list(zope.interface.implementedBy(factory[0]))
+            if len(p) == 1:
+                provides = p[0]
+
+        if provides is None:
+            raise TypeError("Missing 'provides' attribute")            
+
     # Generate a single factory from multiple factories:
     factories = factory
     if len(factories) == 1:
@@ -128,13 +163,14 @@
     elif len(factories) > 1 and len(for_) != 1:
         raise ValueError("Can't use multiple factories and multiple for")
     else:
-        def factory(ob):
-            for f in factories:
-                ob = f(ob)
-            return ob
-        # Store the original factory for documentation
-        factory.factory = factories[0]
+        factory = _rolledUpFactory(factories)
 
+    if permission is not None:
+        if permission == PublicPermission:
+            permission = CheckerPublic
+        checker = InterfaceChecker(provides, permission)
+        factory = _protectedFactory(factory, checker)
+
     if trusted:
         factory = TrustedAdapterFactory(factory)
 
@@ -158,13 +194,46 @@
                     args = ('', iface)
                     )
 
-def utility(_context, provides, component=None, factory=None,
+def _rolledUpFactory(factories):
+    # This has to be named 'factory', aparently, so as not to confuse
+    # apidoc :(
+    def factory(ob):
+        for f in factories:
+            ob = f(ob)
+        return ob
+    # Store the original factory for documentation
+    factory.factory = factories[0]
+    return factory
+
+def _protectedFactory(original_factory, checker):
+    # This has to be named 'factory', aparently, so as not to confuse
+    # apidoc :(
+    def factory(*args):
+        ob = original_factory(*args)
+        try:
+            ob.__Security_checker__ = checker
+        except AttributeError:
+            ob = Proxy(ob, checker)
+        
+        return ob
+    factory.factory = factory
+    return factory
+
+
+def utility(_context, provides=None, component=None, factory=None,
             permission=None, name=''):
     if factory:
         if component:
             raise TypeError("Can't specify factory and component.")
         component = factory()
 
+    if provides is None:
+        provides = list(zope.interface.providedBy(component))
+        if len(provides) == 1:
+            provides = provides[0]
+        else:
+            raise TypeError("Missing 'provides' attribute")
+
     if permission is not None:
         if permission == PublicPermission:
             permission = CheckerPublic

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/metadirectives.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/metadirectives.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/metadirectives.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -178,13 +178,13 @@
         title=_("Interface the component provides"),
         description=_("This attribute specifes the interface the adapter"
                       " instance must provide."),
-        required=True
+        required=False,
         )
 
     for_ = zope.configuration.fields.Tokens(
         title=_("Specifications to be adapted"),
         description=_("This should be a list of interfaces or classes"),
-        required=True,
+        required=False,
         value_type=zope.configuration.fields.GlobalObject(
           missing_value=object(),
           ),
@@ -227,9 +227,15 @@
     factory = zope.configuration.fields.GlobalObject(
         title=_("Subscriber factory"),
         description=_("A factory used to create the subscriber instance."),
-        required=True
+        required=False,
         )
 
+    handler = zope.configuration.fields.GlobalObject(
+        title=_("Handler"),
+        description=_("A callable object that handles events."),
+        required=False,
+        )
+
     provides = zope.configuration.fields.GlobalInterface(
         title=_("Interface the component provides"),
         description=_("This attribute specifes the interface the adapter"
@@ -273,7 +279,7 @@
     provides = zope.configuration.fields.GlobalInterface(
         title=_("Provided interface"),
         description=_("Interface provided by the utility."),
-        required=True
+        required=False,
         )
 
     name = zope.schema.TextLine(

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/registration.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/registration.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/registration.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -18,6 +18,7 @@
 from persistent import Persistent
 
 import zope.event
+from zope.component import subscribers
 from zope.interface import implements
 from zope.security.checker import InterfaceChecker, CheckerPublic
 from zope.security.proxy import Proxy, removeSecurityProxy
@@ -169,6 +170,13 @@
     dependents.addDependent(objectpath)
 
 
+def componentRegistrationEventNotify(componentReg, event):
+    """Subscriber to dispatch registration events for components."""
+    adapters = subscribers((componentReg.component, event), None)
+    for adapter in adapters:
+        pass # getting them does the work
+
+
 def RegisterableMoveSubscriber(registerable, event):
     """A registerable cannot be moved as long as it has registrations in the
     registration manager."""

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/tests/adapter.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/tests/adapter.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/tests/adapter.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -15,8 +15,9 @@
 
 $Id: adapter.py 26551 2004-07-15 07:06:37Z srichter $
 """
-
 import zope.interface
+import zope.component
+import components
 
 class I1(zope.interface.Interface):
     pass
@@ -25,7 +26,9 @@
     pass
 
 class I3(zope.interface.Interface):
-    pass
+    def f1(): pass
+    def f2(): pass
+    def f3(): pass
 
 class IS(zope.interface.Interface):
     pass
@@ -42,9 +45,19 @@
     zope.interface.implements(I2)
 
 class A3(Adapter):
+    zope.component.adapts(components.IContent, I1, I2)
     zope.interface.implements(I3)
 
+class A4:
+    pass
 
+a4 = A4()
+
+class A5:
+    zope.interface.implements(I1, I2)
+
+a5 = A5()
+
 def Handler(content, *args):
     # uninteresting handler
     content.args = getattr(content, 'args', ()) + (args, )

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/tests/test_directives.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/tests/test_directives.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/tests/test_directives.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -40,10 +40,12 @@
 
 from zope.app import zapi
 from zope.app.testing.placelesssetup import PlacelessSetup
+from zope.app.component.interface import queryInterface
 from zope.app.component.metaconfigure import interface
+from zope.app.component.tests.adapter import A1, A2, A3, I1, I3, IS, Handler
+from zope.app.component.tests.components import Content, IApp, Comp, comp
 from zope.app.component.tests.views import IV, IC, V1, R1, IR
 from zope.app.content.interfaces import IContentType
-from zope.app.component.interface import queryInterface
 
 from zope.app.component.tests import module, exampleclass
 from zope.app.component.interface import queryInterface
@@ -100,6 +102,7 @@
 def definePermissions():
     XMLConfig('meta.zcml', zope.app.component)()
 
+
 class Test(PlacelessSetup, unittest.TestCase):
 
     def setUp(self):
@@ -108,19 +111,15 @@
         XMLConfig('meta.zcml', zope.app.security)()
 
     def testSubscriber(self):
-        from zope.app.component.tests.adapter import A1, A2, A3, I3
-        from zope.app.component.tests.adapter import IS
-        from zope.component.tests.components import Content
-
         xmlconfig(StringIO(template % (
-            """
+            '''
             <subscriber
               provides="zope.app.component.tests.adapter.IS"
               factory="zope.app.component.tests.adapter.A3"
-              for="zope.component.tests.components.IContent
+              for="zope.app.component.tests.components.IContent
                    zope.app.component.tests.adapter.I1"
               />
-            """
+            '''
             )))
 
         content = Content()
@@ -133,20 +132,16 @@
         self.assertEqual(a3.context, (content, a1))
 
     def testTrustedSubscriber(self):
-        from zope.app.component.tests.adapter import A1, A2, A3, I3
-        from zope.app.component.tests.adapter import IS
-        from zope.component.tests.components import Content
-
         xmlconfig(StringIO(template % (
-            """
+            '''
             <subscriber
               provides="zope.app.component.tests.adapter.IS"
               factory="zope.app.component.tests.adapter.A3"
-              for="zope.component.tests.components.IContent
+              for="zope.app.component.tests.components.IContent
                    zope.app.component.tests.adapter.I1"
               trusted="yes"
               />
-            """
+            '''
             )))
 
         # With an unproxied object, business as usual
@@ -174,17 +169,14 @@
         self.assert_(removeSecurityProxy(a3).context[0] is content)
 
     def testSubscriber_w_no_provides(self):
-        from zope.app.component.tests.adapter import A1, A2, Handler, I3
-        from zope.component.tests.components import Content
-
         xmlconfig(StringIO(template % (
-            """
+            '''
             <subscriber
-              for="zope.component.tests.components.IContent
+              for="zope.app.component.tests.components.IContent
                    zope.app.component.tests.adapter.I1"
-              factory="zope.app.component.tests.adapter.Handler"
+              handler="zope.app.component.tests.adapter.Handler"
               />
-            """
+            '''
             )))
 
         content = Content()
@@ -194,25 +186,21 @@
         self.assertEqual(content.args, ((a1,),))
         
     def testMultiSubscriber(self):
-        from zope.app.component.tests.adapter import A1, A2, A3, I3
-        from zope.app.component.tests.adapter import IS
-        from zope.component.tests.components import Content
-
         xmlconfig(StringIO(template % (
-            """
+            '''
             <subscriber
               provides="zope.app.component.tests.adapter.IS"
               factory="zope.app.component.tests.adapter.A3"
-              for="zope.component.tests.components.IContent
+              for="zope.app.component.tests.components.IContent
                    zope.app.component.tests.adapter.I1"
               />
             <subscriber
               provides="zope.app.component.tests.adapter.IS"
               factory="zope.app.component.tests.adapter.A2"
-              for="zope.component.tests.components.IContent
+              for="zope.app.component.tests.components.IContent
                    zope.app.component.tests.adapter.I1"
               />
-            """
+            '''
             )))
 
         content = Content()
@@ -228,36 +216,71 @@
 
     def testAdapter(self):
         # Full import is critical!
-        from zope.component.tests.components import Content, IApp, Comp
-
         self.assertEqual(IV(Content(), None), None)
 
         xmlconfig(StringIO(template % (
-            """
+            '''
             <adapter
-              factory="zope.component.tests.components.Comp"
-              provides="zope.component.tests.components.IApp"
-              for="zope.component.tests.components.IContent"
+              factory="zope.app.component.tests.components.Comp"
+              provides="zope.app.component.tests.components.IApp"
+              for="zope.app.component.tests.components.IContent"
               />
-            """
+            '''
             )))
 
         self.assertEqual(IApp(Content()).__class__, Comp)
 
-    def testTrustedAdapter(self):
+    def testAdapter_wo_provides_or_for(self):
         # Full import is critical!
-        from zope.component.tests.components import Content
-        from zope.app.component.tests.adapter import A1, I1
+        self.assertEqual(IV(Content(), None), None)
 
         xmlconfig(StringIO(template % (
-            """
+            '''
             <adapter
+              factory="zope.app.component.tests.components.Comp"
+              />
+            '''
+            )))
+
+        self.assertEqual(IApp(Content()).__class__, Comp)        
+
+    def testAdapter_wo_provides_and_no_implented_fails(self):
+        try:
+            xmlconfig(StringIO(template % (
+                '''
+                <adapter
+                  factory="zope.app.component.tests.adapter.A4"
+                  for="zope.app.component.tests.components.IContent"
+                  />
+                '''
+                )))
+        except ConfigurationError, v:
+            self.assert_("Missing 'provides' attribute" in str(v))
+
+    def testAdapter_wo_provides_and_too_many_implented_fails(self):
+        try:
+            xmlconfig(StringIO(template % (
+                '''
+                <adapter
+                  factory="zope.app.component.tests.adapter.A4"
+                  for="zope.app.component.tests.components.IContent"
+                  />
+                '''
+                )))
+        except ConfigurationError, v:
+            self.assert_("Missing 'provides' attribute" in str(v))
+
+    def testTrustedAdapter(self):
+        # Full import is critical!
+        xmlconfig(StringIO(template % (
+            '''
+            <adapter
               factory="zope.app.component.tests.adapter.A1"
               provides="zope.app.component.tests.adapter.I1"
-              for="zope.component.tests.components.IContent"
+              for="zope.app.component.tests.components.IContent"
               trusted="yes"
               />
-            """
+            '''
             )))
 
         # With an unproxied object, business as usual
@@ -281,20 +304,17 @@
         
 
     def testAdapter_w_multiple_factories(self):
-        from zope.app.component.tests.adapter import A1, A2, A3
-        from zope.component.tests.components import Content, IApp
-
         xmlconfig(StringIO(template % (
-            """
+            '''
             <adapter
               factory="zope.app.component.tests.adapter.A1
                        zope.app.component.tests.adapter.A2
                        zope.app.component.tests.adapter.A3
                       "
-              provides="zope.component.tests.components.IApp"
-              for="zope.component.tests.components.IContent"
+              provides="zope.app.component.tests.components.IApp"
+              for="zope.app.component.tests.components.IContent"
               />
-            """
+            '''
             )))
 
         # The resulting adapter should be an A3, around an A2, around
@@ -313,35 +333,69 @@
         self.assertRaises(ConfigurationError,
                           xmlconfig,
                           StringIO(template % (
-                             """
+                             '''
                              <adapter
                              factory="
                                      "
-                             provides="zope.component.tests.components.IApp"
-                             for="zope.component.tests.components.IContent"
+                             provides="zope.app.component.tests.components.IApp"
+                             for="zope.app.component.tests.components.IContent"
                              />
-                             """
+                             '''
                              )),
                           )
 
     def testMultiAdapter(self):
-        from zope.app.component.tests.adapter import A1, A2, A3, I3
-        from zope.component.tests.components import Content
+        xmlconfig(StringIO(template % (
+            '''
+            <adapter
+              factory="zope.app.component.tests.adapter.A3
+                      "
+              provides="zope.app.component.tests.adapter.I3"
+              for="zope.app.component.tests.components.IContent
+                   zope.app.component.tests.adapter.I1
+                   zope.app.component.tests.adapter.I2"
+              />
+            '''
+            )))
+        content = Content()
+        a1 = A1()
+        a2 = A2()
+        a3 = zapi.queryMultiAdapter((content, a1, a2), I3)
+        self.assertEqual(a3.__class__, A3)
+        self.assertEqual(a3.context, (content, a1, a2))
 
+    def testProtectedMultiAdapter(self):
         xmlconfig(StringIO(template % (
-            """
+            '''
             <adapter
               factory="zope.app.component.tests.adapter.A3
                       "
               provides="zope.app.component.tests.adapter.I3"
-              for="zope.component.tests.components.IContent
+              for="zope.app.component.tests.components.IContent
                    zope.app.component.tests.adapter.I1
                    zope.app.component.tests.adapter.I2
                   "
+              permission="zope.Public"
               />
-            """
+            '''
             )))
+        content = Content()
+        a1 = A1()
+        a2 = A2()
+        a3 = ProxyFactory(zapi.queryMultiAdapter((content, a1, a2), I3))
+        self.assertEqual(a3.__class__, A3)
+        items = [item[0] for item in getTestProxyItems(a3)]
+        self.assertEqual(items, ['f1', 'f2', 'f3'])
 
+    def testMultiAdapter_wo_for_or_provides(self):
+        xmlconfig(StringIO(template % (
+            '''
+            <adapter
+              factory="zope.app.component.tests.adapter.A3"
+              />
+            '''
+            )))
+
         content = Content()
         a1 = A1()
         a2 = A2()
@@ -350,17 +404,14 @@
         self.assertEqual(a3.context, (content, a1, a2))
 
     def testNullAdapter(self):
-        from zope.app.component.tests.adapter import A3, I3
-
         xmlconfig(StringIO(template % (
-            """
+            '''
             <adapter
-              factory="zope.app.component.tests.adapter.A3
-                      "
+              factory="zope.app.component.tests.adapter.A3"
               provides="zope.app.component.tests.adapter.I3"
               for=""
               />
-            """
+            '''
             )))
 
         a3 = zapi.queryMultiAdapter((), I3)
@@ -371,77 +422,84 @@
         self.assertRaises(ConfigurationError,
                           xmlconfig,
                           StringIO(template % (
-                             """
+                             '''
                              <adapter
                              factory="zope.app.component.tests.adapter.A1
                                       zope.app.component.tests.adapter.A2
                                      "
-                             for="zope.component.tests.components.IContent
+                             for="zope.app.component.tests.components.IContent
                                   zope.app.component.tests.adapter.I1
                                   zope.app.component.tests.adapter.I2
                                   "
-                             provides="zope.component.tests.components.IApp"
+                             provides="zope.app.component.tests.components.IApp"
                              />
-                             """
+                             '''
                              )),
                           )
         
         self.assertRaises(ConfigurationError,
                           xmlconfig,
                           StringIO(template % (
-                             """
+                             '''
                              <adapter
                              factory="zope.app.component.tests.adapter.A1
                                       zope.app.component.tests.adapter.A2
                                      "
                              for=""
-                             provides="zope.component.tests.components.IApp"
+                             provides="zope.app.component.tests.components.IApp"
                              />
-                             """
+                             '''
                              )),
                           )
         
 
     def testNamedAdapter(self):
-
-
-        # Full import is critical!
-        from zope.component.tests.components import Content, IApp, Comp
-
         self.testAdapter()
         self.assertEqual(IApp(Content()).__class__, Comp)
         self.assertEqual(zapi.queryAdapter(Content(), IV, 'test'), None)
 
         xmlconfig(StringIO(template % (
-            """
+            '''
             <adapter
-              factory="zope.component.tests.components.Comp"
-              provides="zope.component.tests.components.IApp"
-              for="zope.component.tests.components.IContent"
+              factory="zope.app.component.tests.components.Comp"
+              provides="zope.app.component.tests.components.IApp"
+              for="zope.app.component.tests.components.IContent"
               name="test"
               />
-            """
+            '''
             )))
 
         self.assertEqual(
             zapi.getAdapter(Content(), IApp, "test").__class__, Comp)
 
     def testProtectedAdapter(self):
+        self.assertEqual(IV(Content(), None), None)
 
-        # Full import is critical!
-        from zope.component.tests.components import Content, IApp, Comp
+        xmlconfig(StringIO(template % (
+            '''
+            <adapter
+              factory="zope.app.component.tests.components.Comp"
+              provides="zope.app.component.tests.components.IApp"
+              for="zope.app.component.tests.components.IContent"
+              permission="zope.Public"
+              />
+            '''
+            )))
 
+        adapter = ProxyFactory(IApp(Content()))
+        items = [item[0] for item in getTestProxyItems(adapter)]
+        self.assertEqual(items, ['a', 'f'])
+        self.assertEqual(removeSecurityProxy(adapter).__class__, Comp)
+
+    def testProtectedAdapter_wo_for_or_provides(self):
         self.assertEqual(IV(Content(), None), None)
-
         xmlconfig(StringIO(template % (
-            """
+            '''
             <adapter
-              factory="zope.component.tests.components.Comp"
-              provides="zope.component.tests.components.IApp"
-              for="zope.component.tests.components.IContent"
+              factory="zope.app.component.tests.components.Comp"
               permission="zope.Public"
               />
-            """
+            '''
             )))
 
         adapter = ProxyFactory(IApp(Content()))
@@ -451,89 +509,131 @@
 
     def testAdapterUndefinedPermission(self):
         config = StringIO(template % (
-             """
+             '''
              <adapter
-              factory="zope.component.tests.components.Comp"
-              provides="zope.component.tests.components.IApp"
-              for="zope.component.tests.components.IContent"
+              factory="zope.app.component.tests.components.Comp"
+              provides="zope.app.component.tests.components.IApp"
+              for="zope.app.component.tests.components.IContent"
               permission="zope.UndefinedPermission"
               />
-            """
+            '''
             ))
         self.assertRaises(ValueError, xmlconfig, config, testing=1)
 
     def testUtility(self):
+        self.assertEqual(zapi.queryUtility(IV), None)
 
-        # Full import is critical!
-        from zope.component.tests.components import IApp, comp
+        xmlconfig(StringIO(template % (
+            '''
+            <utility
+              component="zope.app.component.tests.components.comp"
+              provides="zope.app.component.tests.components.IApp"
+              />
+            '''
+            )))
 
+        self.assertEqual(zapi.getUtility(IApp), comp)
+
+    def testUtility_wo_provides(self):
         self.assertEqual(zapi.queryUtility(IV), None)
 
         xmlconfig(StringIO(template % (
-            """
+            '''
             <utility
-              component="zope.component.tests.components.comp"
-              provides="zope.component.tests.components.IApp"
+              component="zope.app.component.tests.components.comp"
               />
-            """
+            '''
             )))
 
         self.assertEqual(zapi.getUtility(IApp), comp)
 
-    def testNamedUtility(self):
+    def testUtility_wo_provides_fails_if_no_provides(self):
+        try:
+            xmlconfig(StringIO(template % (
+                '''
+                <utility
+                  component="zope.app.component.tests.adapter.a4"
+                  />
+                '''
+                )))
+        except ConfigurationError, v:
+            self.assert_("Missing 'provides' attribute" in str(v))
 
-        # Full import is critical!
-        from zope.component.tests.components import IApp, comp
+    def testUtility_wo_provides_fails_if_too_many_provided(self):
+        try:
+            xmlconfig(StringIO(template % (
+                '''
+                <utility
+                  component="zope.app.component.tests.adapter.a5"
+                  />
+                '''
+                )))
+        except ConfigurationError, v:
+            self.assert_("Missing 'provides' attribute" in str(v))
 
+    def testUtility_wo_provides_fails_if_no_implemented(self):
+        try:
+            xmlconfig(StringIO(template % (
+                '''
+                <utility
+                  factory="zope.app.component.tests.adapter.A4"
+                  />
+                '''
+                )))
+        except ConfigurationError, v:
+            self.assert_("Missing 'provides' attribute" in str(v))
+
+    def testUtility_wo_provides_fails_if_too_many_implemented(self):
+        try:
+            xmlconfig(StringIO(template % (
+                '''
+                <utility
+                  factory="zope.app.component.tests.adapter.A5"
+                  />
+                '''
+                )))
+        except ConfigurationError, v:
+            self.assert_("Missing 'provides' attribute" in str(v))
+
+    def testNamedUtility(self):
         self.testUtility()
-
         self.assertEqual(zapi.queryUtility(IV, 'test'), None)
-
         xmlconfig(StringIO(template % (
-            """
+            '''
             <utility
-              component="zope.component.tests.components.comp"
-              provides="zope.component.tests.components.IApp"
+              component="zope.app.component.tests.components.comp"
+              provides="zope.app.component.tests.components.IApp"
               name="test"
               />
-            """
+            '''
             )))
 
         self.assertEqual(zapi.getUtility(IApp, "test"), comp)
 
     def testUtilityFactory(self):
-
-        # Full import is critical!
-        from zope.component.tests.components import IApp, Comp
-
         self.assertEqual(zapi.queryUtility(IV), None)
 
         xmlconfig(StringIO(template % (
-            """
+            '''
             <utility
-              factory="zope.component.tests.components.Comp"
-              provides="zope.component.tests.components.IApp"
+              factory="zope.app.component.tests.components.Comp"
+              provides="zope.app.component.tests.components.IApp"
               />
-            """
+            '''
             )))
 
         self.assertEqual(zapi.getUtility(IApp).__class__, Comp)
 
     def testProtectedUtility(self):
-
-        # Full import is critical!
-        from zope.component.tests.components import IApp, comp
-
         self.assertEqual(zapi.queryUtility(IV), None)
-
         xmlconfig(StringIO(template % (
-            """
+            '''
             <utility
-              component="zope.component.tests.components.comp"
-              provides="zope.component.tests.components.IApp"
+              component="zope.app.component.tests.components.comp"
+              provides="zope.app.component.tests.components.IApp"
               permission="zope.Public"
               />
-            """
+            '''
             )))
 
         utility = ProxyFactory(zapi.getUtility(IApp))
@@ -543,13 +643,13 @@
 
     def testUtilityUndefinedPermission(self):
         config = StringIO(template % (
-             """
+             '''
              <utility
-              component="zope.component.tests.components.comp"
-              provides="zope.component.tests.components.IApp"
+              component="zope.app.component.tests.components.comp"
+              provides="zope.app.component.tests.components.IApp"
               permission="zope.UndefinedPermission"
               />
-            """
+            '''
             ))
         self.assertRaises(ValueError, xmlconfig, config,
                           testing=1)
@@ -576,7 +676,6 @@
 
 
     def testMultiView(self):
-        from zope.app.component.tests.adapter import A1, A2, A3, I3
         xmlconfig(StringIO(template %
             '''
             <view name="test"
@@ -599,7 +698,6 @@
 
 
     def testMultiView_fails_w_multiple_factories(self):
-        from zope.app.component.tests.adapter import A1, A2, A3, I3
         self.assertRaises(
             ConfigurationError,
             xmlconfig,
@@ -617,8 +715,6 @@
             )
 
     def testView_w_multiple_factories(self):
-        from zope.app.component.tests.adapter import A1, A2, A3
-
         xmlconfig(StringIO(template %
             '''
             <view name="test"
@@ -646,8 +742,6 @@
         self.assertEqual(a1.context[0], ob)
 
     def testView_fails_w_no_factories(self):
-        from zope.app.component.tests.adapter import A1, A2, A3
-
         self.assertRaises(ConfigurationError,
                           xmlconfig,
                           StringIO(template %
@@ -799,19 +893,19 @@
             ConfigurationError,
             xmlconfig,
             StringIO(template %
-            """
+            '''
             <view name="test"
                   factory="zope.app.component.tests.views.V1"
                   for="zope.app.component.tests.views.IC"
                   type="zope.app.component.tests.views.IV"
                   allowed_attributes="action index"
                   />
-            """
+            '''
             ))
 
     def testViewUndefinedPermission(self):
         config = StringIO(template % (
-            """
+            '''
             <view name="test"
                   factory="zope.app.component.tests.views.V1"
                   for="zope.app.component.tests.views.IC"
@@ -820,7 +914,7 @@
                   allowed_attributes="action index"
               allowed_interface="zope.app.component.tests.views.IV"
                   />
-            """
+            '''
             ))
         self.assertRaises(ValueError, xmlconfig, config, testing=1)
 
@@ -831,11 +925,11 @@
             zapi.queryMultiAdapter((Ob(), Request(IV)), name='test'), None)
 
         xmlconfig(StringIO(template % (
-            """
+            '''
             <defaultView name="test"
                   for="zope.app.component.tests.views.IC"
                   type="zope.app.component.tests.views.IV"/>
-            """
+            '''
             )))
 
         self.assertEqual(
@@ -850,11 +944,11 @@
         self.assertEqual(
             zapi.queryAdapter(Request(IV), name=u'test'), None)
         xmlconfig(StringIO(template % (
-            """
+            '''
             <resource name="test"
                   factory="zope.app.component.tests.views.R1"
                   type="zope.app.component.tests.views.IV"/>
-            """
+            '''
             )))
 
         self.assertEqual(
@@ -1048,11 +1142,11 @@
     # inherently sets the instances as well as the class attributes.
 
     def testSimpleMethodsPlural(self):
-        declaration = ("""<content class="%s">
+        declaration = ('''<content class="%s">
                             <require
                                 permission="%s"
                                 attributes="m1 m3"/>
-                          </content>"""
+                          </content>'''
                        % (PREFIX+"test_class", P1))
         self.assertDeclaration(declaration, m1P=P1, m3P=P1)
 
@@ -1070,11 +1164,11 @@
         self.assertSetattrState(**state)
 
     def test_set_attributes(self):
-        declaration = ("""<content class="%s">
+        declaration = ('''<content class="%s">
                             <require
                                 permission="%s"
                                 set_attributes="m1 m3"/>
-                          </content>"""
+                          </content>'''
                        % (PREFIX+"test_class", P1))
         apply_declaration(module.template_bracket % declaration)
         checker = selectChecker(module.test_instance)
@@ -1086,11 +1180,11 @@
 
         self.assertEqual(queryInterface(PREFIX+"S"), None)
 
-        declaration = ("""<content class="%s">
+        declaration = ('''<content class="%s">
                             <require
                                 permission="%s"
                                 set_schema="%s"/>
-                          </content>"""
+                          </content>'''
                        % (PREFIX+"test_class", P1, PREFIX+"S"))
         apply_declaration(module.template_bracket % declaration)
 
@@ -1110,11 +1204,11 @@
         self.assertEqual(queryInterface(PREFIX+"S"), None)
         self.assertEqual(queryInterface(PREFIX+"S2"), None)
 
-        declaration = ("""<content class="%s">
+        declaration = ('''<content class="%s">
                             <require
                                 permission="%s"
                                 set_schema="%s %s"/>
-                          </content>"""
+                          </content>'''
                        % (PREFIX+"test_class", P1, PREFIX+"S", PREFIX+"S2"))
         apply_declaration(module.template_bracket % declaration)
 
@@ -1136,11 +1230,11 @@
 
         self.assertEqual(queryInterface(PREFIX+"I"), None)
 
-        declaration = ("""<content class="%s">
+        declaration = ('''<content class="%s">
                             <require
                                 permission="%s"
                                 interface="%s"/>
-                          </content>"""
+                          </content>'''
                        % (PREFIX+"test_class", P1, PREFIX+"I"))
         # m1 and m2 are in the interface, so should be set, and m3 should not:
         self.assertDeclaration(declaration, m1P=P1, m2P=P1)
@@ -1154,12 +1248,12 @@
         self.assertEqual(queryInterface(PREFIX+"I3"), None)
         self.assertEqual(queryInterface(PREFIX+"I4"), None)
 
-        declaration = ("""<content class="%s">
+        declaration = ('''<content class="%s">
                             <require
                                 permission="%s"
                                 interface="  %s
                                              %s  "/>
-                          </content>"""
+                          </content>'''
                        % (PREFIX+"test_class", P1, PREFIX+"I3", PREFIX+"I4"))
         self.assertDeclaration(declaration, m3P=P1, m2P=P1)
 
@@ -1173,10 +1267,10 @@
 
     def testCompositeNoPerm(self):
         # Establish rejection of declarations lacking a permission spec.
-        declaration = ("""<content class="%s">
+        declaration = ('''<content class="%s">
                             <require
                                 attributes="m1"/>
-                          </content>"""
+                          </content>'''
                        % (PREFIX+"test_class"))
         self.assertRaises(ZopeXMLConfigurationError,
                           self.assertDeclaration,
@@ -1185,39 +1279,39 @@
 
 
     def testCompositeMethodsPluralElementPerm(self):
-        declaration = ("""<content class="%s">
+        declaration = ('''<content class="%s">
                             <require
                                 permission="%s"
                                 attributes="m1 m3"/>
-                          </content>"""
+                          </content>'''
                        % (PREFIX+"test_class", P1))
         self.assertDeclaration(declaration,
                                m1P=P1, m3P=P1)
 
     def testCompositeInterfaceTopPerm(self):
-        declaration = ("""<content class="%s">
+        declaration = ('''<content class="%s">
                             <require
                                 permission="%s"
                                 interface="%s"/>
-                          </content>"""
+                          </content>'''
                        % (PREFIX+"test_class", P1, PREFIX+"I"))
         self.assertDeclaration(declaration,
                                m1P=P1, m2P=P1)
 
 
     def testSubInterfaces(self):
-        declaration = ("""<content class="%s">
+        declaration = ('''<content class="%s">
                             <require
                                 permission="%s"
                                 interface="%s"/>
-                          </content>"""
+                          </content>'''
                        % (PREFIX+"test_class", P1, PREFIX+"I2"))
         # m1 and m2 are in the interface, so should be set, and m3 should not:
         self.assertDeclaration(declaration, m1P=P1, m2P=P1)
 
 
     def testMimicOnly(self):
-        declaration = ("""<content class="%s">
+        declaration = ('''<content class="%s">
                             <require
                                 permission="%s"
                                 attributes="m1 m2"/>
@@ -1225,7 +1319,7 @@
                           <content class="%s">
                             <require like_class="%s" />
                           </content>
-                          """ % (PREFIX+"test_base", P1,
+                          ''' % (PREFIX+"test_base", P1,
                 PREFIX+"test_class", PREFIX+"test_base"))
         # m1 and m2 are in the interface, so should be set, and m3 should not:
         self.assertDeclaration(declaration,
@@ -1233,7 +1327,7 @@
 
 
     def testMimicAsDefault(self):
-        declaration = ("""<content class="%s">
+        declaration = ('''<content class="%s">
                             <require
                                 permission="%s"
                                 attributes="m1 m2"/>
@@ -1244,7 +1338,7 @@
                                 permission="%s"
                                 attributes="m2 m3"/>
                           </content>
-                          """ % (PREFIX+"test_base", P1,
+                          ''' % (PREFIX+"test_base", P1,
                 PREFIX+"test_class", PREFIX+"test_base", P2))
 
         # m1 and m2 are in the interface, so should be set, and m3 should not:
@@ -1253,7 +1347,7 @@
 
 
 def apply_declaration(declaration):
-    """Apply the xmlconfig machinery."""
+    '''Apply the xmlconfig machinery.'''
     return xmlconfig(StringIO(declaration))
 
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/container/browser/metaconfigure.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/container/browser/metaconfigure.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/container/browser/metaconfigure.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -18,8 +18,11 @@
 
 __docformat__ = 'restructuredtext'
 
+from zope.app.component.fields import LayerField
 from zope.interface import Interface
 from zope.configuration.fields import GlobalInterface
+from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+from zope.schema import Id
 from zope.app.publisher.browser.viewmeta import page, view
 from zope.app.container.browser.contents import Contents
 from zope.app.container.browser.adding import Adding
@@ -50,8 +53,17 @@
         title=u"The permission needed for add page.",
         required=False)
 
+    layer = LayerField(
+        title=_("The layer the view is in."),
+        description=_("""A skin is composed of layers. It is common to put 
+        skin specific views in a layer named after the skin. If the 'layer'
+        attribute is not supplied, it defaults to 'default'."""),
+        required=False
+        )
 
-def containerViews(_context, for_, contents=None, add=None, index=None):
+
+def containerViews(_context, for_, contents=None, add=None, index=None,
+                   layer=IDefaultBrowserLayer):
     """Set up container views for a given content type."""
 
     if for_ is None:
@@ -60,16 +72,16 @@
     if contents is not None:
         from zope.app.menus import zmi_views
         page(_context, name='contents.html', permission=contents,
-             for_=for_, class_=Contents, attribute='contents',
+             for_=for_, layer=layer, class_=Contents, attribute='contents',
              menu=zmi_views, title=_('Contents'))
 
     if index is not None:
         page(_context, name='index.html', permission=index, for_=for_,
-             class_=Contents, attribute='index')
+             layer=layer, class_=Contents, attribute='index')
 
     if add is not None:
         from zope.app.menus import zmi_actions
-        viewObj = view(_context, name='+', menu=zmi_actions,
+        viewObj = view(_context, name='+', layer=layer, menu=zmi_actions,
                        title=_('Add'), for_=for_, permission=add,
                        class_=Adding)
         viewObj.page(_context, name='index.html', attribute='index')

Modified: Zope3/branches/srichter-blow-services/src/zope/app/container/browser/tests/test_directive.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/container/browser/tests/test_directive.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/container/browser/tests/test_directive.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -21,6 +21,7 @@
 
 import unittest
 from zope.interface import Interface
+from zope.publisher.interfaces import ILayer
 from zope.testing.doctestunit import DocTestSuite
 from zope.app.container.browser.metaconfigure import containerViews
 
@@ -44,6 +45,11 @@
 class I(Interface):
     pass
 
+
+class ITestLayer(ILayer):
+    pass
+
+
 def test_containerViews():
     """
     >>> from zope.app.publisher.browser.menu import menus
@@ -68,7 +74,7 @@
         <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>),
        <InterfaceClass zope.app.menus.zmi_views>,
        u'Contents',
-       <function MenuItemFactory>,
+       <zope.app.publisher.browser.menu.MenuItemFactory object>,
        '')),
      (None,
       <function provideInterface>,
@@ -126,7 +132,7 @@
         <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>),
        <InterfaceClass zope.app.menus.zmi_actions>,
        u'Add',
-       <function MenuItemFactory>,
+       <zope.app.publisher.browser.menu.MenuItemFactory object>,
        'info')),
      (None,
       <function provideInterface>,
@@ -160,7 +166,124 @@
        <class 'zope.app.publisher.browser.viewmeta.+'>,
        'info')))
     """
-       
+
+def test_containerViews_layer():
+    """
+    >>> from zope.app.publisher.browser.menu import menus
+    >>> from zope.interface.interface import InterfaceClass
+    >>> zmi_views = InterfaceClass('zmi_views', __module__='zope.app.menus')
+    >>> menus.zmi_views = zmi_views
+    >>> zmi_actions = InterfaceClass('zmi_actions', __module__='zope.app.menus')
+    >>> menus.zmi_actions = zmi_actions
+
+    >>> context = Context()
+    >>> containerViews(context, for_=I, contents='zope.ManageContent',
+    ...                add='zope.ManageContent', index='zope.View', layer=ITestLayer)
+    >>> context
+    ((('adapter',
+       (<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
+        <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>),
+       <InterfaceClass zope.app.menus.zmi_views>,
+       u'Contents'),
+      <function handler>,
+      ('provideAdapter',
+       (<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
+        <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>),
+       <InterfaceClass zope.app.menus.zmi_views>,
+       u'Contents',
+       <zope.app.publisher.browser.menu.MenuItemFactory object>,
+       '')),
+     (None,
+      <function provideInterface>,
+      ('', <InterfaceClass zope.app.menus.zmi_views>)),
+     (None,
+      <function provideInterface>,
+      ('',
+       <InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
+     (None,
+      <function provideInterface>,
+      ('',
+       <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>)),
+     (None,
+      <function provideInterface>,
+      ('',
+       <InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
+     (('view',
+       <InterfaceClass zope.app.container.browser.tests.test_directive.I>,
+       'contents.html',
+       <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>,
+       <InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
+      <function handler>,
+      ('provideAdapter',
+       (<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
+        <InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
+       <InterfaceClass zope.interface.Interface>,
+       'contents.html',
+       <class 'zope.app.publisher.browser.viewmeta.Contents'>,
+       'info')),
+     (None,
+      <function provideInterface>,
+      ('',
+       <InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
+     (('view',
+       <InterfaceClass zope.app.container.browser.tests.test_directive.I>,
+       'index.html',
+       <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>,
+       <InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
+      <function handler>,
+      ('provideAdapter',
+       (<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
+        <InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
+       <InterfaceClass zope.interface.Interface>,
+       'index.html',
+       <class 'zope.app.publisher.browser.viewmeta.Contents'>,
+       'info')),
+     (('adapter',
+       (<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
+        <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>),
+       <InterfaceClass zope.app.menus.zmi_actions>,
+       u'Add'),
+      <function handler>,
+      ('provideAdapter',
+       (<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
+        <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>),
+       <InterfaceClass zope.app.menus.zmi_actions>,
+       u'Add',
+       <zope.app.publisher.browser.menu.MenuItemFactory object>,
+       'info')),
+     (None,
+      <function provideInterface>,
+      ('', <InterfaceClass zope.app.menus.zmi_actions>)),
+     (None,
+      <function provideInterface>,
+      ('',
+       <InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
+     (None,
+      <function provideInterface>,
+      ('',
+       <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>)),
+     (None,
+      <function provideInterface>,
+      ('',
+       <InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
+     (None,
+      <function provideInterface>,
+      ('', <InterfaceClass zope.interface.Interface>)),
+     (('view',
+       (<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
+        <InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
+       '+',
+       <InterfaceClass zope.interface.Interface>),
+      <function handler>,
+      ('provideAdapter',
+       (<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
+        <InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
+       <InterfaceClass zope.interface.Interface>,
+       '+',
+       <class 'zope.app.publisher.browser.viewmeta.+'>,
+       'info')))
+    """
+
 def test_suite():
     return unittest.TestSuite((
         DocTestSuite(),

Modified: Zope3/branches/srichter-blow-services/src/zope/app/container/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/container/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/container/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -44,7 +44,7 @@
       />
 
   <subscriber
-      factory=".dependency.CheckDependency"
+      handler=".dependency.CheckDependency"
       for="zope.app.container.interfaces.IObjectRemovedEvent"
       trusted="y"
       />
@@ -52,7 +52,7 @@
   <subscriber
       for="zope.app.location.interfaces.ILocation
            zope.app.container.interfaces.IObjectMovedEvent"
-      factory=".contained.dispatchToSublocations"
+      handler=".contained.dispatchToSublocations"
       >
       Handler dispatches moved events to sublocations of the original object.
   </subscriber>

Modified: Zope3/branches/srichter-blow-services/src/zope/app/dublincore/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/dublincore/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/dublincore/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -32,22 +32,22 @@
   </class>
 
   <subscriber
-      factory=".timeannotators.ModifiedAnnotator"
+      handler=".timeannotators.ModifiedAnnotator"
       for="zope.app.event.interfaces.IObjectModifiedEvent"
       />
 
   <subscriber
-      factory=".timeannotators.CreatedAnnotator"
+      handler=".timeannotators.CreatedAnnotator"
       for="zope.app.event.interfaces.IObjectCreatedEvent"
       />
 
   <subscriber
-      factory=".creatorannotator.CreatorAnnotator"
+      handler=".creatorannotator.CreatorAnnotator"
       for="zope.app.event.interfaces.IObjectModifiedEvent"
       />
 
   <subscriber
-      factory=".creatorannotator.CreatorAnnotator"
+      handler=".creatorannotator.CreatorAnnotator"
       for="zope.app.event.interfaces.IObjectCreatedEvent"
       />
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/error/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/error/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/error/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -38,7 +38,7 @@
 
   <subscriber
       for="zope.app.appsetup.IDatabaseOpenedEvent"
-      factory=".bootstrap.bootStrapSubscriber"
+      handler=".bootstrap.bootStrapSubscriber"
       />
 
   <include package=".browser" />

Modified: Zope3/branches/srichter-blow-services/src/zope/app/event/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/event/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/event/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -5,7 +5,7 @@
 
 <subscriber
     for="zope.app.event.interfaces.IObjectEvent" 
-    factory=".objectevent.objectEventNotify"
+    handler=".objectevent.objectEventNotify"
     />
 
 </configure>

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/__init__.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/__init__.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -98,6 +98,6 @@
     def __call__(self, context, request):
         args = (context, request) + self.args
         instance = self._widget_factory(*args)
-        for item in self.kw.items():
-            setattr(instance, item[0], item[1])
+        for name, value in self.kw.items():
+            setattr(instance, name, value)
         return instance

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/__init__.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/__init__.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -18,6 +18,7 @@
 __docformat__ = 'restructuredtext'
 
 from zope.app.form.browser.widget import BrowserWidget, DisplayWidget
+from zope.app.form.browser.widget import UnicodeDisplayWidget
 
 from zope.app.form.browser.textwidgets import TextWidget, BytesWidget
 from zope.app.form.browser.textwidgets import TextAreaWidget, BytesAreaWidget

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/add.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/add.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/add.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -88,11 +88,11 @@
                     kw[str(name)] = data[name]
 
         content = self.create(*args, **kw)
-        adapted = self.schema(content)
 
         errors = []
 
         if self._set_before_add:
+            adapted = self.schema(content)
             for name in self._set_before_add:
                 if name in data:
                     field = self.schema[name]
@@ -108,9 +108,8 @@
 
         content = self.add(content)
 
-        adapted = self.schema(content)
-
         if self._set_after_add:
+            adapted = self.schema(content)
             for name in self._set_after_add:
                 if name in data:
                     field = self.schema[name]
@@ -119,7 +118,7 @@
                     except ValidationError:
                         errors.append(sys.exc_info()[1])
 
-            # We've modified the object, so we need to pubish an
+            # We have modified the object, so we need to publish an
             # object-modified event:
             notify(ObjectModifiedEvent(content))
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/boolwidgets.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/boolwidgets.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/boolwidgets.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -57,6 +57,7 @@
                           id=self.name,
                           cssClass=self.cssClass,
                           extra=self.extra,
+                          value="on",
                           **kw),
             )
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -154,6 +154,14 @@
 
   <view
       type="zope.publisher.interfaces.browser.IBrowserRequest"
+      for="zope.schema.interfaces.IInt"
+      provides="zope.app.form.interfaces.IDisplayWidget"
+      factory=".UnicodeDisplayWidget"
+      permission="zope.Public"
+      />
+
+  <view
+      type="zope.publisher.interfaces.browser.IBrowserRequest"
       for="zope.schema.interfaces.IFloat"
       provides="zope.app.form.interfaces.IInputWidget"
       factory=".FloatWidget"
@@ -162,6 +170,14 @@
 
   <view
       type="zope.publisher.interfaces.browser.IBrowserRequest"
+      for="zope.schema.interfaces.IFloat"
+      provides="zope.app.form.interfaces.IDisplayWidget"
+      factory=".UnicodeDisplayWidget"
+      permission="zope.Public"
+      />
+
+  <view
+      type="zope.publisher.interfaces.browser.IBrowserRequest"
       for="zope.schema.interfaces.IDatetime"
       provides="zope.app.form.interfaces.IInputWidget"
       factory=".DatetimeWidget"

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/interfaces.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/interfaces.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/interfaces.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -176,7 +176,7 @@
 class ISourceQueryView(Interface):
     """View support for querying non-iterable sources
     """
-        
+
     def render(name):
         """Return a rendering of the search form elements
         """

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/metaconfigure.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/metaconfigure.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/metaconfigure.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -20,7 +20,7 @@
 import os
 
 import zope.component
-
+from zope.security.checker import CheckerPublic
 from zope.interface import implementedBy
 from zope.configuration.exceptions import ConfigurationError
 
@@ -47,7 +47,7 @@
     # default basic information
     for_ = None
     layer = IDefaultBrowserLayer
-    permission = 'zope.Public'
+    permission = CheckerPublic
     template = None
     class_ = None
 
@@ -119,7 +119,11 @@
             self.fields = self.names
 
     def _args(self):
-        return (self.name, self.schema, self.label, self.permission,
+        permission = self.permission
+        if permission == 'zope.Public':
+            # Translate public permission to CheckerPublic
+            permission = CheckerPublic
+        return (self.name, self.schema, self.label, permission,
                 self.layer, self.template, self.default_template,
                 self.bases, self.for_, self.fields)
 
@@ -147,7 +151,11 @@
         self.panes = []
 
     def _args(self):
-        return (self.name, self.schema, self.permission, self.layer,
+        permission = self.permission
+        if permission == 'zope.Public':
+            # Translate public permission to CheckerPublic
+            permission = CheckerPublic
+        return (self.name, self.schema, permission, self.layer,
                 self.panes, self.fields, self.template, self.default_template,
                 self.bases, self.for_)
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/metadirectives.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/metadirectives.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/metadirectives.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -234,7 +234,7 @@
     """
     Define an automatically generated edit wizard (multi-page form).
 
-    The editwizard directive creates and register's a view for editing
+    The editwizard directive creates and registers a view for editing
     an object based on a schema.
     """
 
@@ -266,7 +266,7 @@
     """
     Define an automatically generated edit form
 
-    The editform directive creates and register's a view for editing
+    The editform directive creates and registers a view for editing
     an object based on a schema.
     """
 
@@ -318,7 +318,7 @@
     """
     Define an automatically generated display form.
 
-    The schemadisplay directive creates and register's a view for
+    The schemadisplay directive creates and registers a view for
     displaying an object based on a schema.
     """
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/orderedSelectionList.pt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/orderedSelectionList.pt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/orderedSelectionList.pt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -3,7 +3,7 @@
 function moveItems(from, to)
   {
   // shortcuts for selection fields
-  var src = document.getElementById(from); 
+  var src = document.getElementById(from);
   var tgt = document.getElementById(to);
 
   if (src.selectedIndex == -1) selectionError();
@@ -17,7 +17,7 @@
       if (src.options[src.selectedIndex].selected)
         {
         // create a new virtal object with values of item to copy
-        temp = new Option(src.options[src.selectedIndex].text, 
+        temp = new Option(src.options[src.selectedIndex].text,
                       src.options[src.selectedIndex].value);
         // append virtual object to targe
         tgt.options[tgt.length] = temp;
@@ -46,12 +46,12 @@
 function swapFields(a, b)
   {
   // swap items
-  var temp = a.text; 
-  a.text = b.text; 
+  var temp = a.text;
+  a.text = b.text;
   b.text = temp;
   // swap selection
-  var temp = a.selected; 
-  a.selected = b.selected; 
+  var temp = a.selected;
+  a.selected = b.selected;
   b.selected = temp;
   }
 
@@ -61,9 +61,9 @@
   // shortcuts for selection field
   var toSel = document.getElementById(name+".to");
 
-  if (toSel.selectedIndex == -1) 
+  if (toSel.selectedIndex == -1)
       selectionError();
-  else if (toSel.options[0].selected) 
+  else if (toSel.options[0].selected)
       alert("Cannot move further up!");
   else for (var i = 0; i < toSel.length; i++)
     if (toSel.options[i].selected)
@@ -79,9 +79,9 @@
   // shortcuts for selection field
   var toSel = document.getElementById(name+".to");
 
-  if (toSel.selectedIndex == -1) 
+  if (toSel.selectedIndex == -1)
       selectionError();
-  else if (toSel.options[toSel.length-1].selected) 
+  else if (toSel.options[toSel.length-1].selected)
       alert("Cannot move further down!");
   else for (var i = toSel.length-1; i >= 0; i--)
     if (toSel.options[i].selected)
@@ -95,29 +95,29 @@
 function copyDataForSubmit(name)
   {
   // shortcuts for selection field and hidden data field
-  var toSel = document.getElementById(name+".to"); 
+  var toSel = document.getElementById(name+".to");
   var toDataContainer = document.getElementById(name+".toDataContainer");
 
   // delete all child nodes (--> complete content) of "toDataContainer" span
-  while (toDataContainer.hasChildNodes()) 
+  while (toDataContainer.hasChildNodes())
       toDataContainer.removeChild(toDataContainer.firstChild);
 
-  // create new hidden input fields - one for each selection item of 
-  // "to" selection    
+  // create new hidden input fields - one for each selection item of
+  // "to" selection
   for (var i = 0; i < toSel.length; i++)
     {
     // create virtual node with suitable attributes
     var newNode = document.createElement("input");
-    var newAttr = document.createAttribute("name"); 
+    var newAttr = document.createAttribute("name");
     newAttr.nodeValue = name;
     newNode.setAttributeNode(newAttr);
 
-    newAttr = document.createAttribute("type"); 
+    newAttr = document.createAttribute("type");
     newAttr.nodeValue = "hidden";
     newNode.setAttributeNode(newAttr);
 
     newAttr = document.createAttribute("value");
-    newAttr.nodeValue = toSel[i].text;
+    newAttr.nodeValue = toSel[i].value;
     newNode.setAttributeNode(newAttr);
 
     // actually append virtual node to DOM tree
@@ -143,12 +143,12 @@
       </select>
     </td>
     <td>
-      <button type="button" value=" -&gt;" 
+      <button type="button" value=" -&gt;"
           onclick="javascript:from2to()"
           tal:attributes="onClick string:javascript:from2to('${view/name}')"
           >&nbsp;-&gt;</button>
       <br />
-      <button name="to2fromButton" type="button" value="&lt;- " 
+      <button name="to2fromButton" type="button" value="&lt;- "
           onclick="javascript:to2from()"
           tal:attributes="onClick string:javascript:to2from('${view/name}')"
           >&lt;-&nbsp;</button>
@@ -161,23 +161,26 @@
                 tal:attributes="value entry/value"
                 tal:content="entry/text" />
       </select>
+      <input name="foo-empty-marker" type="hidden"
+        tal:attributes="name string:${view/name}-empty-marker"/>
       <span id="toDataContainer"
             tal:attributes="id string:${view/name}.toDataContainer">
-        <script type="text/javascript">
+        <script type="text/javascript" tal:content="string:
+          copyDataForSubmit('${view/name}');">
           // initial copying of field "field.to" --> "field"
           copyDataForSubmit("<i tal:replace="${view/name}"/>");
         </script>
       </span>
     </td>
     <td>
-      <button 
-          name="upButton" type="button" value="^" 
+      <button
+          name="upButton" type="button" value="^"
           onclick="javascript:moveUp()"
           tal:attributes="onClick string:javascript:moveUp('${view/name}')"
           >^</button>
       <br />
-      <button 
-          name="downButton" type="button" value="v" 
+      <button
+          name="downButton" type="button" value="v"
           onclick="javascript:moveDown()"
           tal:attributes="onClick string:javascript:moveDown('${view/name}')"
           >v</button>

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/sequencewidget.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/sequencewidget.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/sequencewidget.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -36,13 +36,13 @@
 
     implements(IInputWidget)
 
-    _type = tuple    
+    _type = tuple
     _data = () # pre-existing sequence items (from setRenderedValue)
 
-    def __init__(self, context, value_type, request, subwidget=None):
+    def __init__(self, context, request, subwidget=None):
         super(SequenceWidget, self).__init__(context, request)
 
-        self.subwidget = None
+        self.subwidget = subwidget
 
     def __call__(self):
         """Render the widget
@@ -234,7 +234,7 @@
         return sequence
 
 class TupleSequenceWidget(SequenceWidget):
-    pass
+    _type = tuple
 
 class ListSequenceWidget(SequenceWidget):
     _type = list


Property changes on: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/source.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/source.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/source.txt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/source.txt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -40,7 +40,7 @@
   >>> import zope.schema
   >>> class SourceList(list):
   ...     zope.interface.implements(zope.schema.interfaces.ISource)
-  
+
 We provide an `ITerms` view for the source:
 
   >>> class Term:
@@ -52,24 +52,24 @@
   ...
   ...     def __init__(self, source, request):
   ...         pass # We don't actually need the source or the request :)
-  ... 
+  ...
   ...     def getTerm(self, value):
   ...         title = unicode(value)
   ...         token = title.encode('base64').strip()
   ...         return Term(title=title, token=token)
-  ... 
+  ...
   ...     def getValue(self, token):
   ...         return token.decode('base64')
 
   >>> from zope.app.testing import ztapi
   >>> from zope.publisher.interfaces.browser import IBrowserRequest
   >>> import zope.app.form.browser.interfaces
-  >>> ztapi.provideAdapter((SourceList, IBrowserRequest), 
+  >>> ztapi.provideAdapter((SourceList, IBrowserRequest),
   ...                      zope.app.form.browser.interfaces.ITerms,
   ...                      ListTerms)
-   
+
 This view just uses the unicode representations of values as titles
-and the base-64 encoding of the titles as tokens.  This is a very 
+and the base-64 encoding of the titles as tokens.  This is a very
 simple strategy that's only approriate when the values have short and
 unique unicode representations.
 
@@ -78,18 +78,18 @@
 query view for the source:
 
   >>> class ListQueryView:
-  ... 
+  ...
   ...     def __init__(self, source, request):
   ...         self.source = source
   ...         self.request = request
-  ... 
+  ...
   ...     def render(self, name):
   ...         return (
   ...             '<input name="%s.string">\n'
   ...             '<input type="submit" name="%s" value="Search">'
   ...             % (name, name)
   ...             )
-  ... 
+  ...
   ...     def results(self, name):
   ...         if name in self.request:
   ...             search_string = self.request.get(name+'.string')
@@ -100,7 +100,7 @@
   ...                         ]
   ...         return None
 
-  >>> ztapi.provideAdapter((SourceList, IBrowserRequest), 
+  >>> ztapi.provideAdapter((SourceList, IBrowserRequest),
   ...                      zope.app.form.browser.interfaces.ISourceQueryView,
   ...                      ListQueryView)
 
@@ -121,7 +121,7 @@
   >>> request = TestRequest()
   >>> widget = zope.app.form.browser.source.SourceInputWidget(
   ...     dog, dog.source, request)
-  
+
 Now if we render the widget, we'll see the input value (initially
 nothing) and a form elements for seaching for values:
 
@@ -168,7 +168,7 @@
 
 If we actually provide some input:
 
-  >>> request.form['field.dog'] = 'foo' 
+  >>> request.form['field.dog'] = 'foo'
 
 then we have input:
 
@@ -266,7 +266,7 @@
 
 We can reuse our terms view:
 
-  >>> ztapi.provideAdapter((MultiSource, IBrowserRequest), 
+  >>> ztapi.provideAdapter((MultiSource, IBrowserRequest),
   ...                      zope.app.form.browser.interfaces.ITerms,
   ...                      ListTerms)
 


Property changes on: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/source.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_add.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_add.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_add.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -24,6 +24,7 @@
 from zope.publisher.interfaces.browser import IDefaultBrowserLayer
 from zope.publisher.browser import TestRequest
 from zope.schema import TextLine, accessors
+from zope.security.checker import CheckerPublic
 
 from zope.app.event.tests.placelesssetup import getEvents
 from zope.app.event.interfaces import IObjectCreatedEvent, IObjectModifiedEvent
@@ -169,7 +170,7 @@
         self.assertEqual(name, 'addthis')
         self.assertEqual(schema, I)
         self.assertEqual(label, 'Add this')
-        self.assertEqual(permission, 'zope.Public')
+        self.assertEqual(permission, CheckerPublic) # 'zope.Public' translated
         self.assertEqual(layer, IDefaultBrowserLayer)
         self.assertEqual(template, 'add.pt')
         self.assertEqual(default_template, 'add.pt')

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_checkboxwidget.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_checkboxwidget.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_checkboxwidget.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -85,6 +85,7 @@
           id="field.foo"
           name="field.foo"
           type="checkbox"
+          value="on"
           />
 
     Hidden rendering:
@@ -114,6 +115,7 @@
           id="field.foo"
           name="field.foo"
           type="checkbox"
+          value="on"
           />
 
     The checkbox widget does not support None values, so a Bool required

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_displaywidget.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_displaywidget.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_displaywidget.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -22,7 +22,7 @@
 from zope.schema import TextLine
 from zope.testing.doctestunit import DocTestSuite
 
-from zope.app.form.browser.widget import DisplayWidget
+from zope.app.form.browser.widget import DisplayWidget, UnicodeDisplayWidget
 
 
 def test_implemented_interfaces():
@@ -86,13 +86,31 @@
 
     >>> widget()
     ''
-    
+
+    If there's no default for the field and the value is missing on
+    the bound object, the empty string should still be displayed::
+
+    >>> field = TextLine(title=u'Title',
+    ...                  __name__=u'title',
+    ...                  required=False)
+
+    >>> class Thing:
+    ...    title = field.missing_value
+
+    >>> field = field.bind(Thing())
+    >>> widget = DisplayWidget(field, TestRequest())
+
+    >>> widget()
+    ''
+
     """
 
 
 def test_suite():
     suite = unittest.TestSuite()
     suite.addTest(DocTestSuite())
+    suite.addTest(DocTestSuite(
+        extraglobs={"DisplayWidget": UnicodeDisplayWidget}))
     return suite
 
 if __name__ == '__main__':

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_intwidget.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_intwidget.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_intwidget.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -28,7 +28,7 @@
 
 class IntWidgetTest(SimpleInputWidgetTest):
     """Documents and tests the int widget.
-        
+
         >>> verifyClass(IInputWidget, IntWidget)
         True
     """

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_sequencewidget.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_sequencewidget.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_sequencewidget.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -25,9 +25,11 @@
 
 from zope.app import zapi
 from zope.app.testing import ztapi
-from zope.app.form.browser import TextWidget, TupleSequenceWidget
-from zope.app.form.browser import ListSequenceWidget
+from zope.app.form.browser import TextWidget, ObjectWidget
+from zope.app.form.browser import TupleSequenceWidget, ListSequenceWidget
+from zope.app.form.browser import SequenceWidget
 from zope.app.form.interfaces import IInputWidget
+from zope.app.form import CustomWidgetFactory
 
 from zope.app.form.browser.tests.test_browserwidget import BrowserWidgetTest
 
@@ -55,9 +57,7 @@
         field = field.bind(self.content)
         request = TestRequest(HTTP_ACCEPT_LANGUAGE='pl')
         request.form['field.foo'] = u'Foo Value'
-        # sequence widgets take value_type as second argument because of double
-        # dispatch
-        self._widget = self._WidgetFactory(field, TextLine(), request)
+        self._widget = self._WidgetFactory(field, request)
 
     def _FieldFactory(self, **kw):
         kw.update({
@@ -83,28 +83,64 @@
         self._widget.request.form['field.foo.0.bar'] = u'hi, mum'
         self.failUnless(self._widget.hasInput())
 
+    def test_customWidgetFactory(self):
+        """Verify that the widget can be constructed via the CustomWidgetFactory
+        (Issue #293)
+        """
+
+        value_type = TextLine(__name__=u'bar')
+        self.field = List( __name__=u'foo', value_type=value_type )
+        request = TestRequest()
+
+        # set up the custom widget factory and verify that it works
+        sw = CustomWidgetFactory(ListSequenceWidget)
+        widget = sw(self.field, request)
+        assert widget.subwidget is None
+        assert widget.context.value_type is value_type
+
+        # set up a variant that specifies the subwidget to use and verify it
+        class PollOption(object) : pass
+        ow = CustomWidgetFactory(ObjectWidget, PollOption)
+        sw = CustomWidgetFactory(ListSequenceWidget, subwidget=ow)
+        widget = sw(self.field, request)
+        assert widget.subwidget is ow
+        assert widget.context.value_type is value_type
+
+    def test_subwidget(self):
+        """This test verifies that the specified subwidget is not ignored.
+        (Issue #293)
+        """
+        self.field = List( __name__=u'foo',
+                           value_type=TextLine(__name__=u'bar'))
+        request = TestRequest()
+
+        class PollOption(object) : pass
+        ow = CustomWidgetFactory(ObjectWidget, PollOption)
+        widget = SequenceWidget(self.field, request, subwidget=ow)
+        assert widget.subwidget is ow
+
     def test_list(self):
         self.field = List(
             __name__=u'foo',
             value_type=TextLine(__name__=u'bar'))
         request = TestRequest()
-        widget = ListSequenceWidget(self.field, TextLine(), request)
+        widget = ListSequenceWidget(self.field, request)
         self.failIf(widget.hasInput())
         self.assertEquals(widget.getInputValue(), [])
 
         request = TestRequest(form={'field.foo.add': u'Add bar'})
-        widget = ListSequenceWidget(self.field, TextLine(), request)
+        widget = ListSequenceWidget(self.field, request)
         self.assert_(widget.hasInput())
         self.assertRaises(ValidationError, widget.getInputValue)
 
         request = TestRequest(form={'field.foo.0.bar': u'Hello world!'})
-        widget = ListSequenceWidget(self.field, TextLine(), request)
+        widget = ListSequenceWidget(self.field, request)
         self.assert_(widget.hasInput())
         self.assertEquals(widget.getInputValue(), [u'Hello world!'])
 
     def test_new(self):
         request = TestRequest()
-        widget = TupleSequenceWidget(self.field, TextLine(), request)
+        widget = TupleSequenceWidget(self.field, request)
         self.failIf(widget.hasInput())
         self.assertEquals(widget.getInputValue(), ())
         check_list = ('input', 'name="field.foo.add"')
@@ -112,7 +148,7 @@
 
     def test_add(self):
         request = TestRequest(form={'field.foo.add': u'Add bar'})
-        widget = TupleSequenceWidget(self.field, TextLine(), request)
+        widget = TupleSequenceWidget(self.field, request)
         self.assert_(widget.hasInput())
         self.assertRaises(ValidationError, widget.getInputValue)
         check_list = (
@@ -123,13 +159,13 @@
 
     def test_request(self):
         request = TestRequest(form={'field.foo.0.bar': u'Hello world!'})
-        widget = TupleSequenceWidget(self.field, TextLine(), request)
+        widget = TupleSequenceWidget(self.field, request)
         self.assert_(widget.hasInput())
         self.assertEquals(widget.getInputValue(), (u'Hello world!',))
 
     def test_existing(self):
         request = TestRequest()
-        widget = TupleSequenceWidget(self.field, TextLine(), request)
+        widget = TupleSequenceWidget(self.field, request)
         widget.setRenderedValue((u'existing',))
         self.assert_(widget.hasInput())
         self.assertEquals(widget.getInputValue(), (u'existing',))
@@ -155,7 +191,7 @@
         request = TestRequest(form={'field.foo.remove_0': u'Hello world!',
             'field.foo.0.bar': u'existing', 'field.foo.1.bar': u'second',
             'remove-selected-items-of-seq-field.foo': u'Remove selected items'})
-        widget = TupleSequenceWidget(self.field, TextLine(), request)
+        widget = TupleSequenceWidget(self.field, request)
         widget.setRenderedValue((u'existing', u'second'))
         self.assertEquals(widget.getInputValue(), (u'second',))
         check_list = (
@@ -168,7 +204,7 @@
     def test_min(self):
         request = TestRequest()
         self.field.min_length = 2
-        widget = TupleSequenceWidget(self.field, TextLine(), request)
+        widget = TupleSequenceWidget(self.field, request)
         widget.setRenderedValue((u'existing',))
         self.assertEquals(widget.getInputValue(), (u'existing',))
         check_list = (
@@ -183,7 +219,7 @@
     def test_max(self):
         request = TestRequest()
         self.field.max_length = 1
-        widget = TupleSequenceWidget(self.field, TextLine(), request)
+        widget = TupleSequenceWidget(self.field, request)
         widget.setRenderedValue((u'existing',))
         self.assertEquals(widget.getInputValue(), (u'existing',))
         s = widget()
@@ -192,7 +228,7 @@
     def test_anonymousfield(self):
         self.field = Tuple(__name__=u'foo', value_type=TextLine())
         request = TestRequest()
-        widget = TupleSequenceWidget(self.field, TextLine(), request)
+        widget = TupleSequenceWidget(self.field, request)
         widget.setRenderedValue((u'existing',))
         s = widget()
         check_list = (

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_textwidget.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_textwidget.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/tests/test_textwidget.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -228,6 +228,34 @@
         self.verifyResult(self._widget(), ["14:39:01 +000"])
 
 
+def test_w_nonrequired_and_missing_value_and_no_inout():
+    """
+    There was a bug that caused the value attribute to be set to
+    'value' under these circumstances.
+
+    >>> from zope.publisher.browser import TestRequest
+    >>> from zope.schema import TextLine
+    >>> field = TextLine(__name__='foo', title=u'on',
+    ...                  required=False, missing_value=u'')
+    >>> request = TestRequest()
+    >>> widget = TextWidget(field, request)
+
+    >>> def normalize(s):
+    ...   return '\\n  '.join(filter(None, s.split(' ')))
+
+    >>> print normalize( widget() )
+    <input
+      class="textType"
+      id="field.foo"
+      name="field.foo"
+      size="20"
+      type="text"
+      value=""
+      />
+
+
+    """
+
 def test_suite():
     return unittest.TestSuite((
         unittest.makeSuite(TextWidgetTest),

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/textwidgets.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/textwidgets.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/textwidgets.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -121,29 +121,23 @@
         super(TextWidget, self).__init__(*args)
 
     def __call__(self):
-        displayMaxWidth = self.displayMaxWidth or 0
-        if displayMaxWidth > 0:
-            return renderElement(self.tag,
-                                 type=self.type,
-                                 name=self.name,
-                                 id=self.name,
-                                 value=self._getFormValue(),
-                                 cssClass=self.cssClass,
-                                 style=self.style,
-                                 size=self.displayWidth,
-                                 maxlength=displayMaxWidth,
-                                 extra=self.extra)
-        else:
-            return renderElement(self.tag,
-                                 type=self.type,
-                                 name=self.name,
-                                 id=self.name,
-                                 value=self._getFormValue(),
-                                 cssClass=self.cssClass,
-                                 style=self.style,
-                                 size=self.displayWidth,
-                                 extra=self.extra)
+        value = self._getFormValue()
+        if value is None or value == self.context.missing_value:
+            value = ''
 
+        kwargs = {'type': self.type,
+                  'name': self.name,
+                  'id': self.name,
+                  'value': value,
+                  'cssClass': self.cssClass,
+                  'style': self.style,
+                  'size': self.displayWidth,
+                  'extra': self.extra}
+        if self.displayMaxWidth:
+            kwargs['maxlength'] = self.displayMaxWidth # XXX This is untested.
+
+        return renderElement(self.tag, **kwargs)
+
     def _toFieldValue(self, input):
         if self.convert_missing_value and input == self._missing:
             value = self.context.missing_value
@@ -151,7 +145,7 @@
             # We convert everything to unicode. This might seem a bit crude,
             # but anything contained in a TextWidget should be representable
             # as a string. Note that you always have the choice of overriding
-            # the method.  
+            # the method.
             try:
                 value = unicode(input)
             except ValueError, v:
@@ -424,6 +418,20 @@
                 return self.context.missing_value
 
 class IntWidget(TextWidget):
+    """Integer number widget.
+
+    Let's make sure that zeroes are rendered properly:
+
+    >>> from zope.schema import Int
+    >>> field = Int(__name__='foo', title=u'on')
+    >>> widget = IntWidget(field, None)
+    >>> widget.setRenderedValue(0)
+
+    >>> 'value="0"' in widget()
+    True
+
+    """
+
     displayWidth = 10
 
     def _toFieldValue(self, input):
@@ -503,6 +511,8 @@
             content = self._data
         else:
             content = self.context.default
+        if content == self.context.missing_value:
+            return ""
         formatter = self.request.locale.dates.getFormatter(
             self._category, (self.displayStyle or None))
         content = formatter.format(content)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/form/browser/widget.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/form/browser/widget.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/form/browser/widget.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -296,7 +296,7 @@
         except ConversionError, error:
             # ConversionError is already a WidgetInputError
             self._error = error
-            raise self._error            
+            raise self._error
 
         # allow missing values only for non-required fields
         if value == field.missing_value and not field.required:
@@ -392,13 +392,27 @@
 
     def __call__(self):
         if self._renderedValueSet():
-            if self._data == self.context.missing_value:
-                return ""
-            return escape(self._data)
+            value = self._data
         else:
-            return escape(self.context.default)
+            value = self.context.default
+        if value == self.context.missing_value:
+            return ""
+        return escape(value)
 
 
+class UnicodeDisplayWidget(BrowserWidget):
+    """Display widget that converts the value to unicode before display."""
+
+    def __call__(self):
+        if self._renderedValueSet():
+            value = self._data
+        else:
+            value = self.context.default
+        if value == self.context.missing_value:
+            return ""
+        return escape(unicode(value))
+
+
 def renderTag(tag, **kw):
     """Render the tag. Well, not all of it, as we may want to / it."""
     attr_list = []
@@ -441,7 +455,7 @@
         items = kw.items()
         items.sort()
         for key, value in items:
-            if value == None:
+            if value is None:
                 value = key
             attr_list.append(u'%s=%s' % (key, quoteattr(unicode(value))))
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/ftests/test_functional.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/ftests/test_functional.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/ftests/test_functional.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -21,6 +21,7 @@
 import transaction
 from zope.app.testing.functional import SampleFunctionalTest, BrowserTestCase
 from zope.app.testing.functional import FunctionalDocFileSuite
+from zope.app.testing.functional import FunctionalTestCase
 
 class CookieFunctionalTest(BrowserTestCase):
 
@@ -121,10 +122,21 @@
         self.assertEquals(response.getBody().strip(), 'aid=aval;bid=bval')
 
 
+class SkinsAndHTTPCaller(FunctionalTestCase):
+
+    def test_skins(self):
+        # Regression test for http://zope.org/Collectors/Zope3-dev/353
+        from zope.app.testing.functional import HTTPCaller
+        http = HTTPCaller()
+        response = http("GET /++skin++Basic HTTP/1.1\n\n")
+        self.assert_("zopetopBasic.css" in str(response))
+
+
 def test_suite():
     suite = unittest.TestSuite()
     suite.addTest(unittest.makeSuite(SampleFunctionalTest))
     suite.addTest(unittest.makeSuite(CookieFunctionalTest))
+    suite.addTest(unittest.makeSuite(SkinsAndHTTPCaller))
     suite.addTest(FunctionalDocFileSuite('doctest.txt'))
     return suite
 

Copied: Zope3/branches/srichter-blow-services/src/zope/app/generations/README.txt (from rev 29088, Zope3/trunk/src/zope/app/generations/README.txt)


Property changes on: Zope3/branches/srichter-blow-services/src/zope/app/generations/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: Zope3/branches/srichter-blow-services/src/zope/app/generations/browser/managers.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/generations/browser/managers.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/generations/browser/managers.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -35,7 +35,7 @@
         return self.request.publication.db
 
     def evolve(self):
-        """Perform a requested evolution 
+        """Perform a requested evolution
 
            This method needs to use the component architecture, so
            we'll set it up:
@@ -90,12 +90,12 @@
            We'll also increase the generation of app1:
 
              >>> app1.generation = 2
-             
+
            Now we can create our view:
 
              >>> view = Managers(None, request)
 
-           Now, if we call it's `evolve` method, it should see that the
+           Now, if we call its `evolve` method, it should see that the
            app1 evolve button was pressed and evolve app1 to the next
            generation.
 
@@ -105,7 +105,7 @@
              2
 
            The demo evolver just writes the generation to a database key:
-           
+
              >>> from zope.app.generations.demo import key
              >>> conn.root()[key]
              (2,)
@@ -148,7 +148,7 @@
              2
              >>> conn.root()[key]
              (2,)
-           
+
            We'd better clean upp:
 
              >>> db.close()
@@ -234,12 +234,12 @@
              >>> app1.generation += 1
 
            so we can evolve it.
-             
+
            Now we can create our view:
 
              >>> view = Managers(None, request)
 
-           We call it's applications method to get data about
+           We call its applications method to get data about
            application generations. We are required to call evolve
            first:
 
@@ -250,19 +250,20 @@
              >>> for info in data:
              ...     print info['id']
              ...     print info['min'], info['max'], info['generation']
-             ...     print 'evolve?', info['evolve']
+             ...     print 'evolve?', info['evolve'] or None
              foo.app1
              0 2 1
              evolve? evolve-app-foo.app1
              foo.app2
              0 0 0
-             evolve? 
+             evolve? None
 
-           We'd better clean upp:
+           We'd better clean up:
 
              >>> db.close()
              >>> tearDown()
-           """
+
+        """
         result = []
 
         db = self._getdb()
@@ -275,7 +276,7 @@
                 manager = managers.get(key)
                 if manager is None:
                     continue
-                
+
                 result.append({
                     'id': key,
                     'min': manager.minimum_generation,

Modified: Zope3/branches/srichter-blow-services/src/zope/app/generations/generations.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/generations/generations.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/generations/generations.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -80,7 +80,7 @@
          >>> context.connection.close()
          >>> conn.close()
          >>> db.close()
-         
+
        """
 
     zope.interface.implements(ISchemaManager)
@@ -94,8 +94,8 @@
                              minimum_generation)
 
         if generation and not package_name:
-            raise ValueError("A package  name must be supplied if the"
-                             "generation is non-zero")
+            raise ValueError("A package name must be supplied if the"
+                             " generation is non-zero")
 
         self.minimum_generation = minimum_generation
         self.generation = generation
@@ -117,9 +117,9 @@
             "%s.evolve%d" % (self.package_name, generation),
             {}, {}, ['*'])
         return evolver.evolve.__doc__
-        
-        
 
+
+
 class Context(object):
     pass
 
@@ -146,15 +146,15 @@
       ...     zope.interface.implements(ISchemaManager)
       ...
       ...     erron = None # Raise an error is asked to evolve to this
-      ... 
+      ...
       ...     def __init__(self, name, minimum_generation, generation):
       ...         self.name, self.generation = name, generation
       ...         self.minimum_generation = minimum_generation
-      ... 
+      ...
       ...     def evolve(self, context, generation):
       ...         if generation == self.erron:
       ...             raise ValueError(generation)
-      ... 
+      ...
       ...         context.connection.root()[self.name] = generation
 
     We also need to set up the component system, since we'll be
@@ -171,9 +171,9 @@
       >>> app2 = FauxApp('app2', 5, 11)
       >>> ztapi.provideUtility(ISchemaManager, app2, name='app2')
 
-    If we great a new database, and evolve it, we'll simply update
+    If we create a new database, and evolve it, we'll simply update
     the generation data:
-    
+
       >>> from ZODB.tests.util import DB
       >>> db = DB()
       >>> conn = db.open()
@@ -202,13 +202,13 @@
       2
       >>> root[generations_key]['app2']
       11
-    
+
     And that the database was updated for that application:
 
       >>> root.get('app1')
       2
       >>> root.get('app2')
-    
+
     If there is an error updating a particular generation, but the
     generation is greater than the minimum generation, then we won't
     get an error from evolve, but we will get a log message.
@@ -238,7 +238,7 @@
 
     Then we'll get an error if we try to evolve, since we can't get
     past 3 and 3 is less than 5:
-    
+
       >>> evolve(db)
       Traceback (most recent call last):
       ...
@@ -286,7 +286,6 @@
     Now, if we use EVOLVEMINIMUM instead, we'll evolve to the minimum
     generation:
 
-
       >>> evolve(db, EVOLVEMINIMUM)
       >>> conn.sync()
       >>> root[generations_key]['app1']
@@ -307,11 +306,12 @@
       GenerationTooHigh: (5, u'app1', 2)
 
     We'd better clean up:
-    
+
       >>> handler.uninstall()
       >>> conn.close()
       >>> db.close()
       >>> tearDown()
+
     """
     conn = db.open()
     try:

Modified: Zope3/branches/srichter-blow-services/src/zope/app/generations/subscriber.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/generations/subscriber.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/generations/subscriber.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -2,7 +2,7 @@
 
 <!--
 <subscriber
-    factory=".generations.evolveSubscriber"
+    handler=".generations.evolveSubscriber"
     for="zope.app.appsetup.IDatabaseOpenedEvent" 
     >
     Evolve to current generation on startup
@@ -11,7 +11,7 @@
 
 <!--
 <subscriber
-    factory=".generations.evolveNotSubscriber"
+    handler=".generations.evolveNotSubscriber"
     for="zope.app.appsetup.IDatabaseOpenedEvent" 
     >
     Don't evolve, but check for minimum generations on startup
@@ -19,7 +19,7 @@
 -->
 
 <subscriber
-    factory=".generations.evolveMinimumSubscriber"
+    handler=".generations.evolveMinimumSubscriber"
     for="zope.app.appsetup.IDatabaseOpenedEvent" 
     >
     Only evolve to minimum generations on startup

Modified: Zope3/branches/srichter-blow-services/src/zope/app/generations/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/generations/tests.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/generations/tests.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -17,10 +17,11 @@
 """
 
 import unittest
-from zope.testing.doctestunit import DocTestSuite
+from zope.testing.doctestunit import DocTestSuite, DocFileSuite
 
 def test_suite():
     return unittest.TestSuite((
+        DocFileSuite('README.txt'),
         DocTestSuite('zope.app.generations.generations'),
         DocTestSuite('zope.app.generations.utility'),
         ))

Modified: Zope3/branches/srichter-blow-services/src/zope/app/generations/utility.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/generations/utility.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/generations/utility.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -78,7 +78,7 @@
 def findObjectsProviding(root, interface):
     """Find all objects in the root that provide the specified interface.
 
-    All sub-objects of the root will also be searched recursively. 
+    All sub-objects of the root will also be searched recursively.
 
     Example:
 
@@ -88,7 +88,7 @@
     >>> class IB(Interface):
     ...     pass
     >>> class IC(IA):
-    ...     pass    
+    ...     pass
 
     >>> class A(dict):
     ...     implements(IA)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/homefolder/README.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/homefolder/README.txt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/homefolder/README.txt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -48,7 +48,7 @@
 
   >>> from zope.app.securitypolicy.interfaces import IPrincipalRoleManager
   >>> roles = IPrincipalRoleManager(baseFolder['stephan'])
-  >>> [(role, str(setting)) 
+  >>> [(role, str(setting))
   ...  for role, setting in roles.getRolesForPrincipal('stephan')]
   [(u'zope.Manager', 'PermissionSetting: Allow')]
 
@@ -62,7 +62,7 @@
   'sc3'
 
 This has the advantage that you can choose your own `IContainer`
-implementation instead of relying on the vanilla folder. 
+implementation instead of relying on the vanilla folder.
 
 Now let's look at some derivations of the same task.
 
@@ -160,7 +160,7 @@
 
   >>> from zope.app.testing import ztapi
   >>> from zope.app.homefolder.interfaces import IHomeFolderManager
-  >>> ztapi.provideUtility(IHomeFolderManager, manager, 'manager') 
+  >>> ztapi.provideUtility(IHomeFolderManager, manager, 'manager')
 
 
 (1) Now we can access the home folder via the adapter:
@@ -174,7 +174,7 @@
 
   >>> from zope.app.traversing.interfaces import IPathAdapter
   >>> from zope.app import zapi
-  >>> zapi.getAdapter(principal, IPathAdapter, 
+  >>> zapi.getAdapter(principal, IPathAdapter,
   ...                 "homefolder") is baseFolder['stephan']
   True
 
@@ -184,8 +184,8 @@
 
   Setup of the Engine
 
-  >>> from zope.app.pagetemplate.engine import Engine 
-  >>> from zope.tales.tales import Context 
+  >>> from zope.app.pagetemplate.engine import Engine
+  >>> from zope.tales.tales import Context
   >>> context = Context(Engine, {'principal': principal})
 
   Executing the TALES expression

Modified: Zope3/branches/srichter-blow-services/src/zope/app/i18n/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/i18n/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/i18n/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -37,14 +37,16 @@
   </localUtility>
   
   <subscriber
-     for="..component.interfaces.registration.IRegistrationActivatedEvent"
-     factory=".translationdomain.setDomainOnActivation"
-     />
+       for=".interfaces.ILocalTranslationDomain
+            ..component.interfaces.registration.IRegistrationActivatedEvent"
+       handler=".translationdomain.setDomainOnActivation"
+       />
 
   <subscriber
-     for="..component.interfaces.registration.IRegistrationDeactivatedEvent"
-     factory=".translationdomain.unsetDomainOnDeactivation"
-     />  
+       for=".interfaces.ILocalTranslationDomain
+            ..component.interfaces.registration.IRegistrationDeactivatedEvent"
+       handler=".translationdomain.unsetDomainOnDeactivation"
+       />  
 
   <!-- Setup Message Catalogs -->
   <content class=".messagecatalog.MessageCatalog">

Modified: Zope3/branches/srichter-blow-services/src/zope/app/i18n/translationdomain.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/i18n/translationdomain.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/i18n/translationdomain.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -223,7 +223,7 @@
 # BBB: Backward compatibility. 12/09/2004
 DomainRegistration = UtilityRegistration
 
-def setDomainOnActivation(event):
+def setDomainOnActivation(domain, event):
     """Set the permission id upon registration activation.
 
     Let's see how this notifier can be used. First we need to create an event
@@ -245,28 +245,14 @@
     Now we pass the event into this function, and the id of the domain should
     be set to 'domain1'.
 
-    >>> setDomainOnActivation(event)
+    >>> setDomainOnActivation(domain1, event)
     >>> domain1.domain
     'domain1'
-
-    If the function is called and the component is not a local domain, nothing
-    is done:
-
-    >>> class Foo:
-    ...     domain = 'no domain'
-    >>> foo = Foo()
-    >>> event = registration.RegistrationActivatedEvent(
-    ...     Registration(foo, 'foo'))
-    >>> setDomainOnActivation(event)
-    >>> foo.domain
-    'no domain'
     """
-    domain = event.object.component
-    if isinstance(domain, TranslationDomain):
-        domain.domain = event.object.name
+    domain.domain = event.object.name
 
 
-def unsetDomainOnDeactivation(event):
+def unsetDomainOnDeactivation(domain, event):
     """Unset the permission id up registration deactivation.
 
     Let's see how this notifier can be used. First we need to create an event
@@ -287,22 +273,8 @@
     Now we pass the event into this function, and the id of the role should be
     set to '<domain not activated>'.
 
-    >>> unsetDomainOnDeactivation(event)
+    >>> unsetDomainOnDeactivation(domain1, event)
     >>> domain1.domain
     '<domain not activated>'
-
-    If the function is called and the component is not a local domain,
-    nothing is done:
-
-    >>> class Foo:
-    ...     domain = 'foo'
-    >>> foo = Foo()
-    >>> event = registration.RegistrationDeactivatedEvent(
-    ...     Registration(foo, 'foo'))
-    >>> unsetDomainOnDeactivation(event)
-    >>> foo.domain
-    'foo'
     """
-    domain = event.object.component
-    if isinstance(domain, TranslationDomain):
-        domain.domain = '<domain not activated>'
+    domain.domain = '<domain not activated>'

Modified: Zope3/branches/srichter-blow-services/src/zope/app/interpreter/python.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/interpreter/python.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/interpreter/python.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -37,7 +37,7 @@
                      {}, # we don't want to get local assignments saved.
                      )
         else:
-            # XXX There atr no tests for this branch
+            # TODO: There are no tests for this branch
             code.exec_(globals,
                        {}, # we don't want to get local assignments saved.
                        )

Modified: Zope3/branches/srichter-blow-services/src/zope/app/intid/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/intid/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/intid/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -26,13 +26,13 @@
   </localUtility>
 
   <subscriber
-      factory=".removeIntIdSubscriber"
+      handler=".removeIntIdSubscriber"
       for="zope.app.location.interfaces.ILocation
            zope.app.container.interfaces.IObjectRemovedEvent"
       />
 
   <subscriber
-      factory=".addIntIdSubscriber"
+      handler=".addIntIdSubscriber"
       for="zope.app.location.interfaces.ILocation
            zope.app.container.interfaces.IObjectAddedEvent"
       />

Modified: Zope3/branches/srichter-blow-services/src/zope/app/introspector/introspector.pt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/introspector/introspector.pt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/introspector/introspector.pt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -136,7 +136,7 @@
         </tr>
 
         <tr>
-          <th>
+          <th class="introspector">
             <tal:span i18n:translate="">Description</tal:span>:
           </th>
           <td>

Modified: Zope3/branches/srichter-blow-services/src/zope/app/locales/de/LC_MESSAGES/zope.mo
===================================================================
(Binary files differ)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/locales/de/LC_MESSAGES/zope.po
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/locales/de/LC_MESSAGES/zope.po	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/locales/de/LC_MESSAGES/zope.po	2005-02-10 15:21:18 UTC (rev 29102)
@@ -3,38 +3,39 @@
 # Stephan Richter <stephan.richter at tufts.edu>, 2003, 2004.
 # Philipp von Weitershausen <philikon at philikon.de>, 2003.
 # Claudia Walenzyk <cwalenzyk at yahoo.com>, 2003.
+# Egon Frerich <e.frerich at nord-com.net>, 2005.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: zope\n"
 "POT-Creation-Date: Tue Nov  9 12:08:38 2004\n"
-"PO-Revision-Date: 2004-09-07 12:14-0400\n"
-"Last-Translator: Stephan Richter <stephan.richter at tufts.edu>\n"
-"Language-Team: German <zope3-dev at zope.org>\n"
+"PO-Revision-Date: 2005-01-26 17:44+0100\n"
+"Last-Translator: Egon Frerich <e.frerich at nord-com.net>\n"
+"Language-Team: German <<zope3-dev at zope.org>>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: KBabel 1.9\n"
+"X-Generator: KBabel 1.0.2\n"
 
 #: src/zope/app/adapter/adapter.py:291
 #: src/zope/app/presentation/pagefolder.py:56
 #: src/zope/app/presentation/presentation.py:92
 msgid "For interface"
-msgstr "Gegebenes Interface"
+msgstr "Gegebene Schnittstelle"
 
 #: src/zope/app/adapter/adapter.py:292
 msgid "The interface of the objects being adapted"
-msgstr "Das Interface des adaptierten Objektes"
+msgstr "Die Schnittstelle des adaptierten Objektes"
 
 #: src/zope/app/adapter/adapter.py:297
 #: src/zope/app/component/metadirectives.py:268
 #: src/zope/app/utility/interfaces.py:48
 msgid "Provided interface"
-msgstr "Bereitgestelltes Interface"
+msgstr "Bereitgestellte Schnittstelle"
 
 #: src/zope/app/adapter/adapter.py:298
 msgid "The interface provided"
-msgstr "Das bereitgestellte Interface"
+msgstr "Die bereitgestellte Schnittstelle"
 
 #: src/zope/app/adapter/adapter.py:304
 #: src/zope/app/component/metadirectives.py:195
@@ -87,9 +88,9 @@
 "which was designed to aid the developer directly to the desired information. "
 "Below you see a short description of every module."
 msgstr ""
-"Module sind normalerweise von einander abhängig, da sie durch Links "
-"Referenzen zu anderen Modulen bereitstellen. Jedes Modul hat ein \"Thema\" "
-"das es folgt, sodass der Entwickler schneller die gewünschten Informationen "
+"Module sind normalerweise voneinander abhängig, da sie Referenzen zu "
+"anderen Modulen durch Links bereitstellen. Jedes Modul hat ein \"Thema\", "
+"dem es folgt, sodass der Entwickler schneller die gewünschten Informationen "
 "finden kann. In den folgenden Abschnitten finden Sie kurze Beschreibungen "
 "für jedes Modul."
 
@@ -106,11 +107,11 @@
 "on a module, the module's menu will appear below. In the menu you have then "
 "navigational means to access the documentation content of the module."
 msgstr ""
-"Willkommen zum Zope 3 API Dokumentationstool. Die bereitgestellte "
-"Dokumentation hier ist in diskrete Dokumentationsmodule unterteilt. Sie "
-"können eine Liste aller Module in der links-oben platzierten Box auf Ihrem "
-"Bildschirm sehen. Wenn Sie auf ein Modul klicken, dann öffnet sich ds "
-"Modulmenü darunter. Das Menü bietet dann Navigationsmöglichkeiten um auf den "
+"Willkommen zum Zope 3 API Dokumentationstool. Die hier bereitgestellte "
+"Dokumentation ist in diskrete Dokumentationsmodule unterteilt. Sie "
+"können eine Liste aller Module in der links oben platzierten Box auf Ihrem "
+"Bildschirm sehen. Wenn Sie auf ein Modul klicken, dann öffnet sich das "
+"Modulmenü darunter. Das Menü bietet dann Navigationsmöglichkeiten, um auf den "
 "Inhalt der Dokumentation zugreifen zu können."
 
 #: src/zope/app/apidoc/browser/menu.pt:5
@@ -171,26 +172,27 @@
 "    "
 msgstr ""
 "\n"
-"Dieses Modul erlaubt es Ihnen einen Überblick über die Module und Klassen "
-"aus denen die Zope 3 Framework und deren unterstützenden Pakten zu erhalten. "
-"Es gibt zwei Wege durch die Module zu navigieren um Klassen in denen Sie "
-"interessiert sind zu finden.\n"
+"Mit diesem Modul können Sie einen Überblick über die Module und Klassen "
+"erhalten, die im Zope 3 Framework und ihren unterstützenden Paketen "
+" enthalten sind. Sie können auf zwei Wegen durch die Module navigieren, um "
+" die Sie interessierenden Klassen zu finden.\n"
 "\n"
-"Die erste Methode besteht darin einen Teil des Pythonpfades der Klasse "
-"einzugeben und das Modul sucht dann im Klassenregistrar nach "
+"Die erste Methode besteht darin, einen Teil des Pythonpfades der Klasse "
+"einzugeben. Das Modul sucht im Klassenregister nach "
 "Übereinstimmungen. Das Menü gibt dann eine Liste aller Treffer aus.\n"
 "\n"
 "Für die zweite Methode klicken Sie einfach auf den \"Zope Quellcode browsen"
-"\" link. In dem Hauptfenster sehen Sie eine Verzeichnisauflistung aller Zope "
-"3 Wurzelmodule. Sie können auf diese Module klicken um ihren Inhalt yu "
+"\" Link. In dem Hauptfenster sehen Sie eine Verzeichnisauflistung aller Zope "
+"3 Wurzelmodule. Sie können auf diese Module klicken, um ihren Inhalt zu "
 "erforschen. Wenn eine Klasse gefunden wurde, wird sie als fetter Eintrag in "
 "der Liste angezeigt.\n"
 "\n"
-"Der Dokumentationsinhalt einer Klasse bietet Ihnen eine unglaubliche Menge "
-"an Informationen. Es werden Ihnen nicht nur die Basisklassen,implementierte "
-"Interfaces, Attribute und Methoden angezeigt, aber zeigt auch welches "
-"Interface welches Attribut (oder Methode) erfordert und die Erlaubnis die "
-"benötigt wird es zu benutzen."
+"Der Dokumentationsinhalt einer Klasse bietet Ihnen eine erstaunliche Menge "
+"an Informationen. Es werden Ihnen nicht nur die Basisklassen, implementierte "
+"Schnittstellen, Attribute und Methoden angezeigt, sondern auch, welches "
+"Attribut (oder welche Methode) bei der Implementierung einer Schnittstelle"
+" erforderlich ist sowie die notwendige Berechtigung für den Zugriff auf das "
+"Attribut."
 
 #: src/zope/app/apidoc/classmodule/__init__.py:612
 msgid "Zope 3 root."
@@ -225,7 +227,7 @@
 #: src/zope/app/apidoc/classmodule/class_index.pt:29
 #: src/zope/app/apidoc/classmodule/class_index.pt:163
 msgid "(C-based class)"
-msgstr "(C-basierende Klasse)"
+msgstr "(C-basierte Klasse)"
 
 #: src/zope/app/apidoc/classmodule/class_index.pt:35
 #: src/zope/app/apidoc/ifacemodule/index.pt:40
@@ -234,11 +236,11 @@
 
 #: src/zope/app/apidoc/classmodule/class_index.pt:40
 msgid "Implemented Interfaces"
-msgstr "Implementierte Interfaces:"
+msgstr "Implementierte Schnittstellen:"
 
 #: src/zope/app/apidoc/classmodule/class_index.pt:55
 msgid "There are no implemented interfaces."
-msgstr "Es gibt keine implementierten Interfaces."
+msgstr "Es gibt keine implementierten Schnittstellen."
 
 #: src/zope/app/apidoc/classmodule/class_index.pt:61
 msgid "Attributes/Properties"
@@ -308,7 +310,7 @@
 #: src/zope/app/catalog/interfaces.py:66 src/zope/app/catalog/text.py:35
 #: src/zope/app/component/metadirectives.py:429
 msgid "Interfaces"
-msgstr "Interfaces"
+msgstr "Schnittstellen"
 
 #: src/zope/app/apidoc/ifacemodule/__init__.py:78
 msgid ""
@@ -327,16 +329,16 @@
 "    "
 msgstr ""
 "\n"
-"Alle benutzten und wichtigen Interfaces sind durch den Interface Dienst "
-"registriert. Während es möglich wäre alle Interfaces auf einmal anzuzeigen, "
-"ist es jedoch schwer für den Benutzer in einer solchen vollen Liste den "
-"Ãœberblick zu behalten. Daher wurden Interfaces mit gleichem beginnenden "
-"Pfaden zusammengebunden.\n"
+"Alle benutzten und wichtigen Schnittstellen sind durch den Schnittstellen-Dienst "
+"registriert. Zwar könnten alle Schnittstellen auf einmal angezeigt werden, doch "
+"ist es für den Benutzer schwer, in einer solchen übervollen Liste den "
+"Ãœberblick zu behalten. Daher wurden Schnittstellen mit gleichem beginnenden "
+"Pfaden zusammengefaßt.\n"
 "\n"
-"Die Dokumentation eines Interfaces bietet auch eine große Vielfalt an "
-"Informationen, natürlich einschließlich der deklarierten Attribute/Felder "
-"und Methoden, aber auch der vorhandenen Adaptoren, Diensten und Werkzeugen "
-"welche dieses Interface zur Verfügung stellen."
+"Die Dokumentation einer Schnittstelle stellt ebenfalls eine große Vielfalt an "
+"Informationen bereit, eingeschlossen selbstverständlich die deklarierten "
+"Attribute/Felder und Methoden, aber auch die vorhandenen Adapter, Dienste "
+"und Werkzeuge, welche diese Schnittstelle zur Verfügung stellt."
 
 #: src/zope/app/apidoc/ifacemodule/browser.py:206
 msgid "required"
@@ -344,7 +346,7 @@
 
 #: src/zope/app/apidoc/ifacemodule/browser.py:208
 msgid "optional"
-msgstr "optional"
+msgstr "wahlfrei"
 
 #: src/zope/app/apidoc/ifacemodule/index.pt:101
 msgid "There are no methods specified."
@@ -356,7 +358,7 @@
 
 #: src/zope/app/apidoc/ifacemodule/index.pt:114
 msgid "Adapters where this interface is required:"
-msgstr "Adapter, für welche dieses Interface notwendig ist:"
+msgstr "Adapter, für welche diese Schnittstelle notwendig ist:"
 
 #: src/zope/app/apidoc/ifacemodule/index.pt:127
 #: src/zope/app/apidoc/ifacemodule/index.pt:168
@@ -373,7 +375,7 @@
 
 #: src/zope/app/apidoc/ifacemodule/index.pt:155
 msgid "Adapters that provide this interface:"
-msgstr "Adapter, die dieses Interface liefern:"
+msgstr "Adapter, die diese Schnittstelle liefern:"
 
 #: src/zope/app/apidoc/ifacemodule/index.pt:172
 msgid "requires:"
@@ -381,11 +383,11 @@
 
 #: src/zope/app/apidoc/ifacemodule/index.pt:179
 msgid "No interface required."
-msgstr "Kein Interface notwendig."
+msgstr "Keine Schnittstelle notwendig."
 
 #: src/zope/app/apidoc/ifacemodule/index.pt:190
 msgid "There are no adapters registered for this interface."
-msgstr "Es gibt keine registrierten Adapter für dieses Interface."
+msgstr "Es gibt keine registrierten Adapter für diese Schnittstelle."
 
 #: src/zope/app/apidoc/ifacemodule/index.pt:200
 msgid "Other Information"
@@ -396,15 +398,14 @@
 msgstr "Fabriken"
 
 #: src/zope/app/apidoc/ifacemodule/index.pt:207
-#, fuzzy
 msgid "A list of factories that create objects implementing this interface."
 msgstr ""
-"Eine Liste von Fabriken, die solche Objekte erstellen, die dieses Interface "
-"liefern."
+"Eine Liste von Fabriken, die diejenigen Objekte erstellen, die diese Schnittstelle "
+"implementieren."
 
 #: src/zope/app/apidoc/ifacemodule/index.pt:226
 msgid "A list of utilities that are are registered to provide this interface."
-msgstr "Eine Liste registrierter Werkzeuge, welche dieses Interface liefern."
+msgstr "Eine Liste registrierter Werkzeuge, welche diese Schnittstelle bereitstellen."
 
 #: src/zope/app/apidoc/ifacemodule/index.pt:237
 msgid "Class:"
@@ -415,15 +416,15 @@
 "A list of services (usually just one) that are are registered to provide "
 "this interface."
 msgstr ""
-"Eine Liste von registrierten Diensten (üblicherweise nur einer), die dieses "
-"Interface liefern."
+"Eine Liste von registrierten Diensten (üblicherweise nur einer), die diese "
+"Schnittstelle bereitstellen."
 
 #: src/zope/app/apidoc/ifacemodule/index.pt:268
 msgid ""
 "A list of classes that implement this interface. This might duplicate the "
 "entries in Utilities and Services."
 msgstr ""
-"Eine Liste von Klassen welche dieses Interface implementieren. Dies "
+"Eine Liste von Klassen, welche diese Schnittstelle implementieren. Dies "
 "dupliziert wahrscheinlich Einträge unter den Werkzeugen und Diensten."
 
 #: src/zope/app/apidoc/ifacemodule/menu.pt:4
@@ -431,7 +432,7 @@
 "Note: These are only interfaces that are registered with the Interface "
 "Service."
 msgstr ""
-"Anmerkung: Dies sind nur Interfaces, die mit dem Interfacedienst registriert "
+"Anmerkung: Dies sind nur Schnittstellen, die mit dem Schnittstellendienst registriert "
 "sind."
 
 #: src/zope/app/apidoc/servicemodule/__init__.py:74
@@ -463,7 +464,7 @@
 "    "
 msgstr ""
 "\n"
-"Das Dienstmodul erlaubt dem Leser durch alle definierten Dienste zu browsen. "
+"Das Dienste-Modul erlaubt dem Leser, durch alle definierten Dienste zu browsen. "
 "Es benutzt den Dienstidentifikationsschlüssel. Im Allgemeinen können Dienste "
 "wie folgt abgefragt werden::\n"
 "\n"
@@ -471,22 +472,23 @@
 "  >>> service = zapi.getService('ServiceName')\n"
 "\n"
 "\n"
-"Hier haben wir 'None; als Standardkontext, was bedeutet daß immer der global "
-"Dienst zurückgegeben wird. Wenn Sie ein Objekt, welches einen Platz im "
-"Objektbaum besitzt, dann wird ihnen der nächste Dienst yurückgegeben, was "
-"durchaus ein lokaler Dienst sein kann. Das erste ARgument ist der "
-"Dienstname, welcher durch jeden, der im Menü aufgleisteten Namen ersetzt "
+"Hier benutzen wir die Vorgabe 'None' als Kontext, wodurch immer der globale "
+"Dienst zurückgegeben wird. Wenn Sie ein Objekt benutzen, welches einen Platz im "
+"Objektbaum besitzt, dann wird Ihnen im allgemeinen der nächstliegende Dienst "
+"zurückgegeben, was "
+"durchaus ein lokaler Dienst sein kann. Das erste Argument ist der "
+"Dienstname, welcher durch jeden der im Menü aufgelisteten Namen ersetzt "
 "werden kann.\n"
 "\n"
-"Für jeden Dienst werden dann die Attribute und Methoden des Dienstinterfaces "
-"presäntiert. Am Ende steht eine Liste aller registrierten Implementationen "
+"Für jeden Dienst werden dann die Attribute und Methoden der Dienste-Schnittstellen "
+"präsentiert. Am Ende steht eine Liste aller registrierten Implementationen "
 "des Dienstes."
 
 #: src/zope/app/apidoc/servicemodule/index.pt:17
 #: src/zope/app/apidoc/classmodule/class_index.pt:84
 #: src/zope/app/apidoc/classmodule/class_index.pt:125
 msgid "Interface:"
-msgstr "Interface:"
+msgstr "Schnittstelle:"
 
 #: src/zope/app/apidoc/servicemodule/index.pt:26
 #: src/zope/app/apidoc/utilitymodule/index.pt:30
@@ -550,15 +552,15 @@
 "    "
 msgstr ""
 "\n"
-"Werkzeuge sind auch via einem Dienst registriert, sodaß es einfach ist eine "
-"Liste aller verfügbaren Werkzeuge zu erstellen. Ein Werkzeug wird durch das "
-"bereitgestellte Interface und einem Namen, welcher leer sein kann, "
-"identifiziert. Das Menü stellt Ihnen eine Liste von Werkzeuginterfaces "
-"bereit und ihre Untereinträge sind die Namen der verschiedenen "
+"Werkzeuge sind auch via einem Dienst registriert, so daß es einfach ist, eine "
+"Liste aller verfügbaren Werkzeuge zu erstellen. Ein Werkzeug wird durch die "
+"bereitgestellte Schnittstelle und einem Namen, welcher leer sein kann, "
+"identifiziert. Das Menü liefert Ihnen eine Liste mit Schnittstellen, die von Werkzeugen "
+"bereitgestellt werden, und als Untereinträge die Namen  verschiedener "
 "Implementationen.\n"
 "\n"
-"Und wieder listet die Dokumentation des Werkzeugs all Attribute/Felder und "
-"Methoden auf, die das Werkzeug bereitstellt und bietet einen Link zur "
+"Und wieder listet die Dokumentation des Werkzeugs alle Attribute/Felder und "
+"Methoden auf, die das Werkzeug bereitstellt, und bietet einen Link zur "
 "eigentlichen Implementation."
 
 #: src/zope/app/apidoc/utilitymodule/index.pt:17
@@ -611,28 +613,29 @@
 "    "
 msgstr ""
 "\n"
-"Das Presäntations- oder Ansichtmodul ist ein bisschen verückt, da eine "
-"Ansicht oder Ressourcenicht durch ein einfaches Interface oder Namen "
-"identifiyiert werden kann; es benötigt vier oder fünf Aussagen. Daher läßt "
-"Sie das Menü den Presäntationstypen und das Interface wählen für welche die "
-"Ansicht gefunden werden sollte.\n"
+"Das Präsentations- oder Ansichtmodul ist ein bisschen verrückt, da eine "
+"Ansicht oder Ressource nicht durch eine einzelne Schnittstelle oder einen Namen "
+"identifiziert werden kann; sie benötigt vier oder fünf Informationsteile. Daher läßt "
+"Sie das Menü den Präsentationstypen und die Schnittstelle wählen, aufgrund "
+"deren Ansichten gefunden werden sollen.\n"
 "\n"
-"Die Voreinstellung lässt Ansichten aus, die kein Interface benötigen "
-"(``None``) oder die nur ``zope.interface.Interface`` benötigen. Um diese "
-"zusätylichen Ansichten su sehen, klicken Sie auf \"All Ansichten zeigen\".\n"
+"Die Voreinstellung lässt Ansichten aus, die keine Schnittstelle "
+"(``None``) oder nur die ``zope.interface.Interface`` benötigen. Um diese "
+"zusätzlichen Ansichten zu sehen, klicken Sie auf \"Alle Ansichten zeigen\".\n"
 "\n"
-"Wenn Sie dann auf \"Anzeigen\" klicken, werden Sie mit einer Liste aller "
-"Ansichten anwendbarer Ansichten presäntiert. Die Ansichten sind nach Ebenen "
+"Wenn Sie dann auf \"Zeigen\" klicken, wird Ihnen eine Liste aller "
+"anwendbarer Ansichten präsentiert. Die Ansichten sind nach Ebenen "
 "sortiert. Die Ansichten sind hauptsächlich durch ihren Namen identifiziert, "
-"da diese in der URL verwendet werden. Informationen über eine Ansicht "
-"reichen von dem benötigtem Interface und dem Presäntationstypen bis zur "
-"Zugriffsgenehmigung. Wenn möglich, versucht das Szstem auch Informationen "
-"von der Ansichtsfabrik zu bekommen, wie zum Beispiel die Klasse, das "
-"Template oder die Ressource.\n"
+"da dieser z.B. in der URL verwendet wird. Informationen über eine Ansicht "
+"reichen von der benötigten Schnittstelle und dem Präsentationstypen bis zur "
+"Berechtigung. Wenn möglich, versucht das System auch Informationen "
+"aus der Ansichtsfabrik zu bekommen, wie zum Beispiel die Klasse, die "
+"Schablone oder die Ressource.\n"
 "\n"
-"Total unabhängig von alledem gibt es einen Link namens \"Zeige Häute und "
-"Ebenen\" welcher Sie zu einer einfachen Ãœbersicht bringt, die Ihnen die "
-"Abhängigkeiten zwichen den Ebenen und Häuten zeigt."
+"Total unabhängig von dieser Suchmöglichkeit gibt es einen Link namens "
+"\"Anzeigeformen und Ebenen anzeigen\", welcher Sie zu einer einfachen "
+"Ãœbersicht bringt, die Ihnen die "
+"Abhängigkeiten zwischen den Ebenen und Anzeigeformenn zeigt."
 
 #: src/zope/app/apidoc/viewmodule/index.pt:28
 msgid "required:"
@@ -668,7 +671,7 @@
 
 #: src/zope/app/apidoc/viewmodule/index.pt:89
 msgid "There are no views for this interface and presentation type."
-msgstr "Es gibt keine Ansichten für dieses Interface und Präsentationstyp."
+msgstr "Es gibt keine Ansichten für diese Schnittstelle und diesen Präsentationstyp."
 
 #: src/zope/app/apidoc/viewmodule/menu.pt:18
 msgid "Presentation Type:"
@@ -680,15 +683,15 @@
 
 #: src/zope/app/apidoc/viewmodule/menu.pt:36
 msgid "Show Skins and Layers"
-msgstr "Themen und Ebenen anzeigen"
+msgstr "Anzeigeformen und Ebenen anzeigen"
 
 #: src/zope/app/apidoc/viewmodule/menu.pt:8
 msgid "Enter the interface name:"
-msgstr "Geben Sie einen Interface-Namen ein:"
+msgstr "Geben Sie einen Schnittstellen-Namen ein:"
 
 #: src/zope/app/apidoc/viewmodule/skin_layer.pt:15
 msgid "Skin-Layer Tree"
-msgstr "Themen-Ebenen Baum"
+msgstr "Anzeigeformen-Ebenen Baum"
 
 #: src/zope/app/apidoc/viewmodule/skin_layer.pt:28
 msgid "(default)"
@@ -696,7 +699,7 @@
 
 #: src/zope/app/apidoc/viewmodule/skin_layer.pt:4
 msgid "Skins &amp; Layers"
-msgstr "Themen &amp; Ebenen"
+msgstr "Anzeigeformen &amp; Ebenen"
 
 #: src/zope/app/apidoc/viewmodule/skin_layer.pt:8
 msgid ""
@@ -707,11 +710,11 @@
 "which the skin or layer was declared."
 msgstr ""
 "In dem folgenden kleinen Baum sehen Sie eine Aufzählung aller in Zope 3 "
-"erhältlichen Themen (große fette Schrift) und die Ebenen (kleine fette "
-"Schrift) für jedes Thema. Unter jedem Eintrag sehen Sie dann die "
+"erhältlichen Anzeigeformen (große fette Schrift) und die Ebenen (kleine fette "
+"Schrift) für jede Anzeigeform. Unter jedem Eintrag sehen Sie dann die "
 "Dokumentation die für jeden Eintrag registriert wurde. Im Falle von globalen "
-"Themen und Ebenen zeigt die Dokumentation die Datei und Zeilennummer in "
-"welcher das Thema oder die Ebene definiert wurde."
+"Anzeigeformen und Ebenen zeigt die Dokumentation die Datei und Zeilennummer, in "
+"welcher die Anzeigeform oder die Ebene definiert wurde."
 
 #: src/zope/app/apidoc/zcmlmodule/__init__.py:192
 msgid "ZCML Reference"
@@ -736,16 +739,16 @@
 "    "
 msgstr ""
 "\n"
-"Dieses Modul yeigt Ihnen eine komplette Liste von ZCML Direktiven und ist "
-"daher bestens als Referenz zu gebrauhen. Das Menü stellt einen Baum bereit, "
-"der die Direktiven nach Namespace orgnisiert.\n"
+"Dieses Modul zeigt Ihnen eine komplette Liste der ZCML Direktiven und ist "
+"daher bestens als Referenz zu gebrauchen. Das Menü stellt einen Baum bereit, "
+"der die Direktiven nach Namensräumen organisiert.\n"
 "\n"
 "Der Dokumentationsinhalt für jede Direktive beschreibt Ihnen alle Attribute "
-"und deren Semantik. Es stellt auch einen Link zu dem Interface bereit "
-"welches durch die Direktive erfüllt wird. Wenn erhältlich, wird Ihnen sogar "
+"und deren Semantik. Es stellt auch einen Link zu der Schnittstelle bereit, "
+"welche durch die Direktive erfüllt wird. Wenn erhältlich, wird Ihnen sogar "
 "die Datei, in der die Direktive deklariert wurde, angezeigt. Am Ende der "
-"Liste werden alle vorhandenen Unterdirektiven aufgezeigt, einschließlich des "
-"implementierten Interfaces und deren Attribute."
+"Liste werden alle vorhandenen Unterdirektiven aufgezeigt, einschließlich der "
+"implementierten Schnittstellen und deren Attribute."
 
 #: src/zope/app/apidoc/zcmlmodule/index.pt:13
 msgid "File:"
@@ -787,11 +790,9 @@
 msgstr "Unterdirektiven"
 
 #: src/zope/app/apidoc/zcmlmodule/menu.pt:4
-#, fuzzy
-msgid ""
-"Namespaces that are not full URLs start with \"http://namespaces.zope.org/\"."
+msgid "Namespaces that are not full URLs start with \"http://namespaces.zope.org/\"."
 msgstr ""
-"Namensräume, die nicht als volle URIs angegeben sind, starten mit \"http://"
+"Namensräume, die nicht als volle URLs angegeben sind, beginnen mit \"http://"
 "namespaces.zope.org\"."
 
 #: src/zope/app/applicationcontrol/browser/configure.zcml:10
@@ -863,8 +864,7 @@
 msgstr "Sekunden"
 
 #: src/zope/app/applicationcontrol/browser/server-control.pt:13
-msgid ""
-"If you specify a time of 0 seconds, then the server will do a hard shutdown."
+msgid "If you specify a time of 0 seconds, then the server will do a hard shutdown."
 msgstr ""
 "Wenn Sie eine Zeit von 0 Sekunden eingeben, dann wird der Server sofort "
 "angehalten (hard shutdown)."
@@ -984,16 +984,14 @@
 
 #: src/zope/app/bundle/browser/bundle.pt:123
 msgid "Click \"Activate bundle\" to perform the above actions."
-msgstr ""
-"Klicken Sie auf \"Bündel aktivieren\" um die o.a. Aktionen durchzuführen."
+msgstr "Klicken Sie auf \"Bündel aktivieren\" um die o.a. Aktionen durchzuführen."
 
 #: src/zope/app/bundle/browser/bundle.pt:127
 msgid "activate-bundle-button"
 msgstr "Aktivieren"
 
 #: src/zope/app/bundle/browser/bundle.pt:137
-msgid ""
-"Click \"Deactivate bundle\" to unregister all registrations in this bundle."
+msgid "Click \"Deactivate bundle\" to unregister all registrations in this bundle."
 msgstr ""
 "Klicken Sie auf \"Bündel deaktivieren\", um alle Registrierungen in diesem "
 "Bündel nichtig zu machen."
@@ -1097,8 +1095,7 @@
 
 #: src/zope/app/cache/browser/cacheableedit.pt:5
 msgid "This edit form allows you to associate a cache with this object."
-msgstr ""
-"Dieses Formular erlaubt Ihnen, einen Cache für dieses Objekt zu definieren."
+msgstr "Dieses Formular erlaubt Ihnen, einen Cache für dieses Objekt zu definieren."
 
 #: src/zope/app/cache/browser/cacheableedit.pt:52
 #: src/zope/app/cache/browser/ramstats.pt:37
@@ -1146,8 +1143,7 @@
 
 #: src/zope/app/cache/browser/configure.zcml:6
 msgid "Caches can be used to make your site run faster."
-msgstr ""
-"Caches können dayu benutzt werden, ihre Seite schneller laufen zu lassen."
+msgstr "Caches können dayu benutzt werden, ihre Seite schneller laufen zu lassen."
 
 #: src/zope/app/cache/browser/ramedit.pt:20
 msgid "Maximum cached entries"
@@ -1261,8 +1257,7 @@
 msgid ""
 "Index items based on multi-value fields with                  orderable "
 "values"
-msgstr ""
-"Indexeinträge die auf multiwerten Felderen mit sortierbaren Werten basieren"
+msgstr "Indexeinträge die auf multiwerten Felderen mit sortierbaren Werten basieren"
 
 #: src/zope/app/catalog/browser/configure.zcml:82
 #: src/zope/app/catalog/browser/configure.zcml:91
@@ -1277,11 +1272,11 @@
 #: src/zope/app/component/metadirectives.py:149
 #: src/zope/app/component/metadirectives.py:467
 msgid "Interface"
-msgstr "Interface"
+msgstr "Schnittstelle"
 
 #: src/zope/app/catalog/interfaces.py:65 src/zope/app/catalog/text.py:34
 msgid "Objects will be adapted to this interface"
-msgstr "Objekte werden zu diesem Interface adaptiert"
+msgstr "Objekte werden zu dieser Schnittstelle adaptiert"
 
 #: src/zope/app/catalog/interfaces.py:71 src/zope/app/catalog/text.py:41
 #: src/zope/app/site/browser/interfacedetail.pt:46
@@ -1304,7 +1299,7 @@
 
 #: src/zope/app/component/metadirectives.py:106
 msgid "View attributes that are also allowed if the user has permission."
-msgstr ""
+msgstr "Attribute einer Ansicht, die angezeigt werden, wenn der Nutzer hierfür die Berechtigung hat."
 
 #: src/zope/app/component/metadirectives.py:108
 msgid ""
@@ -1314,20 +1309,23 @@
 "        you can make the permission also apply to the extra attributes\n"
 "        on the view object."
 msgstr ""
+"\n"
+"      'Berechtigung' bezieht sich voreingestellt nur auf das Anzeigen der\n"
+"      Ansicht und mögliche Unteransichten. Durch die Angabe von\n"
+"      'allowed_attributes' kann die Berechtigung auch auf die extra Attribute\n"
+"      der Ansicht erweitert werden."
 
 #: src/zope/app/component/metadirectives.py:123
-#, fuzzy
 msgid "The name of the resource."
-msgstr "Name des Ursprungsstatus."
+msgstr "Name der Ressource."
 
 #: src/zope/app/component/metadirectives.py:124
 msgid "The name shows up in URLs/paths. For example 'foo'."
-msgstr ""
+msgstr "Der Name erscheint in URL-Pfaden. Zum Beispiel 'foo'."
 
 #: src/zope/app/component/metadirectives.py:130
-#, fuzzy
 msgid "The interface this component provides."
-msgstr "Das bereitgestellte Interface"
+msgstr "Die von dieser Komponente bereitgestellte Schnittstelle"
 
 #: src/zope/app/component/metadirectives.py:131
 msgid ""
@@ -1335,6 +1333,9 @@
 "        A view can provide an interface.  This would be used for\n"
 "        views that support other views."
 msgstr ""
+"\n"
+"       Eine Ansicht kann eine Schnittstelle bereitstellen. Diese würde\n"
+"       für Ansichten genutzt werden, die andere Ansichten unterstützen."
 
 #: src/zope/app/component/metadirectives.py:139
 #: src/zope/app/component/metadirectives.py:502
@@ -1343,34 +1344,31 @@
 msgstr "Anfrage-Typ"
 
 #: src/zope/app/component/metadirectives.py:154
-#, fuzzy
 msgid "Interface type"
-msgstr "Interface-Name"
+msgstr "Schnittstellen-Typ"
 
 #: src/zope/app/component/metadirectives.py:164
 msgid "Adapter factory/factories"
-msgstr ""
+msgstr "Adapter-Fabrik/Fabriken"
 
 #: src/zope/app/component/metadirectives.py:165
-#, fuzzy
-msgid ""
-"A list of factories (usually just one) that create the adapter instance."
+msgid "A list of factories (usually just one) that create the adapter instance."
 msgstr ""
-"Eine Liste von registrierten Diensten (üblicherweise nur einer), die dieses "
-"Interface liefern."
+"Eine Liste von Fabriken (üblicherweise nur eine), die die Adapter-Instanz "
+"erzeugt."
 
 # Default: "Interface>"
 #: src/zope/app/component/metadirectives.py:172
 #: src/zope/app/component/metadirectives.py:228
-#, fuzzy
 msgid "Interface the component provides"
-msgstr "Interface"
+msgstr "Schnittstelle, die die Komponente bereitstellt"
 
 #: src/zope/app/component/metadirectives.py:173
 #: src/zope/app/component/metadirectives.py:229
-msgid ""
-"This attribute specifes the interface the adapter instance must provide."
+msgid "This attribute specifes the interface the adapter instance must provide."
 msgstr ""
+"Dieses Attribut spezifiziert die Schnittstelle, die von der Adapter-Instanz "
+"bereitgestellt werden muß"
 
 #: src/zope/app/component/metadirectives.py:179
 msgid "Specifications to be adapted"
@@ -1394,9 +1392,8 @@
 
 #: src/zope/app/component/metadirectives.py:203
 #: src/zope/app/component/metadirectives.py:251
-#, fuzzy
 msgid "Trusted"
-msgstr "Ãœbersetzen"
+msgstr "Vertrauenswürdig"
 
 #: src/zope/app/component/metadirectives.py:204
 msgid ""
@@ -1409,22 +1406,29 @@
 "        objects.\n"
 "        "
 msgstr ""
+"Mache den Adapter vertrauenswürdig\n"
+"\n"
+"       Vertrauenswürdige Adapter erlauben unbehinderten Zugriff auf\n"
+"       die Objekte, die sie adaptieren.  Wenn Objekte, die gesicherte\n"
+"       Vertreter (Proxies) haben, adaptiert werden sollen, erhalten sie\n"
+"       einen gesicherten Vertreter des Adapters der originalen Objekte\n"
+"       und nicht einen originalen Adapter zu den gesicherten Vertretern\n"
+"       der Objekte."
 
 #: src/zope/app/component/metadirectives.py:222
 msgid "Subscriber factory"
-msgstr ""
+msgstr "Abonnent-Fabrik"
 
 #: src/zope/app/component/metadirectives.py:223
 msgid "A factory used to create the subscriber instance."
-msgstr ""
+msgstr "Eine Fabrik zum Erzeugen einer Abonennten-Instanz."
 
 #: src/zope/app/component/metadirectives.py:235
 msgid "Interfaces or classes that this subscriber depends on"
 msgstr ""
 
 #: src/zope/app/component/metadirectives.py:245
-msgid ""
-"This subscriber is only available, if the principal has this permission."
+msgid "This subscriber is only available, if the principal has this permission."
 msgstr ""
 
 #: src/zope/app/component/metadirectives.py:252
@@ -1440,9 +1444,8 @@
 msgstr ""
 
 #: src/zope/app/component/metadirectives.py:269
-#, fuzzy
 msgid "Interface provided by the utility."
-msgstr "Das Interface das von dem Werkzeug bereitgestellt wird"
+msgstr "Die von dem Werkzeug bereitgestellte Schnittstelle"
 
 #: src/zope/app/component/metadirectives.py:275
 msgid ""
@@ -1478,8 +1481,7 @@
 
 #: src/zope/app/component/metadirectives.py:295
 #: src/zope/app/component/metadirectives.py:486
-msgid ""
-"Text suitable for use in the 'add content' menu of a management interface"
+msgid "Text suitable for use in the 'add content' menu of a management interface"
 msgstr ""
 
 #: src/zope/app/component/metadirectives.py:301
@@ -1504,9 +1506,8 @@
 msgstr ""
 
 #: src/zope/app/component/metadirectives.py:326
-#, fuzzy
 msgid "The interface this view is the default for."
-msgstr "Gibt das Interface an, für welches dieser Menüeintrag gilt."
+msgstr "Die Schnittstelle, die für diese Ansicht voreingestellt ist."
 
 #: src/zope/app/component/metadirectives.py:327
 msgid ""
@@ -1531,9 +1532,8 @@
 msgstr ""
 
 #: src/zope/app/component/metadirectives.py:342
-#, fuzzy
 msgid "The layer the resource is in."
-msgstr "Die Themenebene, für welche die Ansicht registriert ist"
+msgstr "Die Ebene, für welche die Ansicht registriert ist"
 
 #: src/zope/app/component/metadirectives.py:353
 msgid "View attributes that are also allowed if user has permission."
@@ -1554,9 +1554,8 @@
 msgstr ""
 
 #: src/zope/app/component/metadirectives.py:394
-#, fuzzy
 msgid "One or more interfaces"
-msgstr "Interfaces entfernen:"
+msgstr ""
 
 #: src/zope/app/component/metadirectives.py:406
 msgid ""
@@ -1637,9 +1636,8 @@
 
 #: src/zope/app/component/metadirectives.py:48
 #: src/zope/app/component/metadirectives.py:312
-#, fuzzy
 msgid "Factory"
-msgstr "Fabriken"
+msgstr "Fabrik"
 
 #: src/zope/app/component/metadirectives.py:49
 msgid ""
@@ -1656,9 +1654,8 @@
 msgstr "Ebene"
 
 #: src/zope/app/component/metadirectives.py:61
-#, fuzzy
 msgid "Specifications of the objects to be viewed"
-msgstr "Das Interface der Objekte welches angesehen wird"
+msgstr "Die Spezifikationen der Objekte, die angezeigt werden"
 
 #: src/zope/app/component/metadirectives.py:62
 msgid ""
@@ -1682,9 +1679,8 @@
 msgstr ""
 
 #: src/zope/app/component/metadirectives.py:83
-#, fuzzy
 msgid "The layer the view is in."
-msgstr "Die Themenebene, für welche die Ansicht registriert ist"
+msgstr "Die Ebene, für welche die Ansicht registriert ist"
 
 #: src/zope/app/component/metadirectives.py:84
 msgid ""
@@ -1754,19 +1750,19 @@
 
 #: src/zope/app/container/browser/contents.py:244
 msgid "You didn't specify any ids to remove."
-msgstr "Sie haben keine Ids zum Löschen angegeben."
+msgstr "Sie haben keine IDs zum Löschen angegeben."
 
 #: src/zope/app/container/browser/contents.py:256
 msgid "You didn't specify any ids to copy."
-msgstr "Sie haben keine Ids zum Kopieren angegeben."
+msgstr "Sie haben keine IDs zum Kopieren angegeben."
 
 #: src/zope/app/container/browser/contents.py:276
 msgid "You didn't specify any ids to cut."
-msgstr "Sie haben keine Ids zum Ausschneiden angegeben."
+msgstr "Sie haben keine IDs zum Ausschneiden angegeben."
 
 #: src/zope/app/container/browser/contents.py:64
 msgid "You didn't specify any ids to rename."
-msgstr "Sie haben keine Ids zum Umbenennen angegeben."
+msgstr "Sie haben keine IDs zum Umbenennen angegeben."
 
 #: src/zope/app/container/browser/metaconfigure.py:66
 #: src/zope/app/site/browser/configure.zcml:19
@@ -1827,7 +1823,7 @@
 
 #: src/zope/app/debugskin/unauthorized.pt:8
 msgid "You're not allowed in here."
-msgstr "Sie sind hier nicht erlaubt."
+msgstr "Sie sind hierfür nicht zugelassen."
 
 #: src/zope/app/demo/insensitivefolder/configure.zcml:30
 msgid "Case insensitive Folder"
@@ -1934,7 +1930,7 @@
 
 #: src/zope/app/dtmlpage/interfaces.py:35
 msgid "The source of the dtml page."
-msgstr "Der Quellcode der DTML Page"
+msgstr "Der Quellcode der DTML-Seite"
 
 #: src/zope/app/dublincore/browser/configure.zcml:10
 #: src/zope/app/zopetop/widget_macros.pt:186
@@ -1986,13 +1982,12 @@
 
 #: src/zope/app/errorservice/browser/configure.zcml:35
 msgid "Error Reporting Service for Logging Errors"
-msgstr "Fehlermeldedienst für Logging Fehler"
+msgstr "Fehlerberichtsdienst über Fehler im Logbuch"
 
 #: src/zope/app/errorservice/browser/error.pt:10
-msgid ""
-"This page lists the exceptions that have occurred in this site recently."
+msgid "This page lists the exceptions that have occurred in this site recently."
 msgstr ""
-"Diese Seite listet die Ausnahmen auf, die kürzlich in dieser Webseite "
+"Diese Seite listet die Ausnahmen auf, die kürzlich auf diesem Webplatz "
 "aufgetreten sind."
 
 #: src/zope/app/errorservice/browser/error.pt:15
@@ -2024,11 +2019,11 @@
 
 #: src/zope/app/errorservice/browser/error_config.pt:18
 msgid "Number of exceptions to keep"
-msgstr "Anzahl der zu behaltenden Ausnahmen"
+msgstr "Anzahl der zu aufzubewahrenden Ausnahmen"
 
 #: src/zope/app/errorservice/browser/error_config.pt:26
 msgid "Copy exceptions to the event log"
-msgstr "Ausnahmen in das Ereignis-Log kopieren"
+msgstr "Ausnahmen in das Ereignis-Logbuch kopieren"
 
 #: src/zope/app/errorservice/browser/error_config.pt:3
 msgid "Configure Error Log"
@@ -2043,8 +2038,8 @@
 "You can configure how many exceptions should be kept and whether the "
 "exceptions should be copied to Zope's event log file(s)."
 msgstr ""
-"Sie können einstellen, wie viele Ausnahmen behalten werden sollen und ob die "
-"Ausnahmen in Zopes Ereignislog-Datei(en) kopiert werden soll."
+"Sie können einstellen, wie viele Ausnahmen aufbewahrt und "
+"ob die Ausnahmen in Zopes Ereignislog-Datei(en) kopiert werden sollen."
 
 #: src/zope/app/errorservice/browser/errorentry.pt:11
 msgid "Exception traceback"
@@ -2076,7 +2071,7 @@
 
 #: src/zope/app/errorservice/browser/errorentry.pt:78
 msgid "return-to-log-button"
-msgstr "Zurück zum Log"
+msgstr "Zurück zum Logbuch"
 
 #: src/zope/app/errorservice/browser/errorentry.pt:9
 msgid "Header"
@@ -2221,9 +2216,8 @@
 msgstr ""
 
 #: src/zope/app/form/browser/boolwidgets.py:112
-#, fuzzy
 msgid "False"
-msgstr "Datei"
+msgstr ""
 
 #: src/zope/app/form/browser/boolwidgets.py:94
 #: src/zope/app/form/browser/boolwidgets.py:99
@@ -2284,19 +2278,19 @@
 # Default: "Remove"
 #: src/zope/app/form/browser/source.py:359
 msgid "MultipleSourceInputWidget-remove"
-msgstr ""
+msgstr "Löschen"
 
 # Default: "Nothing"
 #: src/zope/app/form/browser/source.py:50
 #: src/zope/app/form/browser/source.py:152
 #: src/zope/app/form/browser/source.py:160
 msgid "SourceDisplayWidget-missing"
-msgstr ""
+msgstr "Fehlt"
 
 # Default: "Invalid value"
 #: src/zope/app/form/browser/source.py:61
 msgid "SourceDisplayWidget-invalid"
-msgstr ""
+msgstr "Ungültig"
 
 #: src/zope/app/fssync/browser/__init__.py:158
 msgid "required argument 'name' missing"
@@ -2304,7 +2298,7 @@
 
 #: src/zope/app/fssync/browser/__init__.py:217
 msgid "Up-to-date check failed:"
-msgstr "Up-to-date Check fehlgeschlagen:"
+msgstr "Up-to-date Prüfung fehlgeschlagen:"
 
 #: src/zope/app/fssync/browser/__init__.py:92
 msgid "Content-Type is not application/x-snarf"
@@ -2331,8 +2325,7 @@
 msgstr "Datenbanken-Schemas"
 
 #: src/zope/app/generations/browser/managers.pt:18
-msgid ""
-"The database was updated to generation ${generation} for ${application}."
+msgid "The database was updated to generation ${generation} for ${application}."
 msgstr ""
 "Die Datenbank wurde auf Generation ${generation} für ${application} "
 "aktualisiert."
@@ -2428,8 +2421,7 @@
 
 #: src/zope/app/i18n/browser/synchronize.pt:122
 msgid "No connection could be made to remote data source."
-msgstr ""
-"Es konnte keine Verbindung mit der Fremddatenquelle hergestellt werden."
+msgstr "Es konnte keine Verbindung mit der Fremddatenquelle hergestellt werden."
 
 #: src/zope/app/i18n/browser/synchronize.pt:26
 msgid "Server URL"
@@ -2532,7 +2524,7 @@
 #: src/zope/app/i18nfile/browser/file_edit.pt:39
 #: src/zope/app/i18nfile/browser/image_edit.pt:40
 msgid "Default Language"
-msgstr "Vorgegebene Sprache"
+msgstr "Voreingestellte Sprache"
 
 #: src/zope/app/i18nfile/browser/file_edit.pt:54
 #: src/zope/app/i18nfile/browser/image_edit.pt:55
@@ -2577,17 +2569,15 @@
 msgstr "Bearbeitungsformular"
 
 #: src/zope/app/i18nfile/browser/i18nfile.py:47
-msgid ""
-"This edit form allows you to make changes to the properties of this file."
+msgid "This edit form allows you to make changes to the properties of this file."
 msgstr ""
-"Dieses Berarbeitungsformular erlaubt es Ihnen, Änderungen an den "
+"Dieses Bearbeitungsformular erlaubt es Ihnen, Änderungen an den "
 "Einstellungen ihrer Datei vorzunehmen."
 
 #: src/zope/app/i18nfile/browser/i18nimage.py:32
-msgid ""
-"This edit form allows you to make changes to the properties of this image."
+msgid "This edit form allows you to make changes to the properties of this image."
 msgstr ""
-"Dieses Berarbeitungsformular erlaubt es Ihnen, Änderungen an den "
+"Dieses Bearbeitungsformular erlaubt es Ihnen, Änderungen an den "
 "Einstellungen ihres Bildes vorzunehmen."
 
 #: src/zope/app/i18nfile/browser/image_edit.pt:85
@@ -2620,13 +2610,12 @@
 msgid ""
 "       Use the object-introspection facility to discover       and browse "
 "interfaces and classes.       "
-msgstr ""
-"Nutzen Sie die Objektintrospektion um Interfaces und Klassen zu erkunden."
+msgstr "Nutzen Sie die Objektintrospektion, um Schnittstellen und Klassen zu erkunden."
 
 # Default: "Introspect Object Classes and Interfaces"
 #: src/zope/app/introspector/configure.zcml:6
 msgid "zope.app.introspector.Introspect"
-msgstr "Objektklassen und -interfaces introspektieren"
+msgstr "Objektklassen und -Schnittstellen introspektieren"
 
 #: src/zope/app/introspector/introspector.pt:203
 msgid "modify-button"
@@ -2634,7 +2623,7 @@
 
 #: src/zope/app/introspector/introspector.pt:26
 msgid "Interface Browser"
-msgstr "Interface-Browser"
+msgstr "Schnittstellen-Browser"
 
 #: src/zope/app/introspector/introspector.pt:66
 msgid "class-attributes"
@@ -2642,11 +2631,11 @@
 
 #: src/zope/app/introspector/marker.pt:109
 msgid "Remove Interfaces:"
-msgstr "Interfaces entfernen:"
+msgstr "Schnittstellen entfernen:"
 
 #: src/zope/app/introspector/marker.pt:124
 msgid "Add Interfaces:"
-msgstr "Interfaces hinzufügen:"
+msgstr "Schnittstellen hinzufügen:"
 
 #: src/zope/app/introspector/marker.pt:27
 #: src/zope/app/introspector/introspector.pt:121
@@ -2669,17 +2658,17 @@
 # Default: "Module"
 #: src/zope/app/introspector/marker.pt:56
 msgid "python-module"
-msgstr "Modul"
+msgstr "Python-Modul"
 
 #: src/zope/app/introspector/marker.pt:74
 #: src/zope/app/introspector/introspector.pt:166
 msgid "Interfaces from Class"
-msgstr "Interfaces der Klasse"
+msgstr "Schnittstellen der Klasse"
 
 #: src/zope/app/introspector/marker.pt:92
 #: src/zope/app/introspector/introspector.pt:185
 msgid "Interfaces from Object"
-msgstr "Interfaces des Objektes"
+msgstr "Schnittstellen des Objektes"
 
 #: src/zope/app/mail/configure.zcml:7
 msgid "send-mail-permission"
@@ -2757,8 +2746,7 @@
 
 #: src/zope/app/menus.zcml:17
 msgid "Menu of objects to be added to content folders"
-msgstr ""
-"Menü von Objekten die als Inhalt zu dem Ordner hinzugefügt werden können"
+msgstr "Menü von Objekten, die als Inhalt zu dem Ordner hinzugefügt werden können"
 
 #: src/zope/app/menus.zcml:21
 msgid "Menu for objects to be added according to containment constraints"
@@ -2768,12 +2756,11 @@
 
 #: src/zope/app/menus.zcml:27
 msgid "Menu of objects to be added to site management folders"
-msgstr ""
-"Menü von Objekten die Webseitenverwaltungs-Ordnern hinzugefügt werden können"
+msgstr "Menü von Objekten, die Webplatzverwaltungs-Ordnern hinzugefügt werden können"
 
 #: src/zope/app/menus.zcml:31
 msgid "Menu of database connections to be added"
-msgstr "Menü der Datenbank Verbindungen die hinzugefügt werden können"
+msgstr "Menü der Datenbank Verbindungen, die hinzugefügt werden können"
 
 #: src/zope/app/menus.zcml:35
 msgid "Menu of addable configuration objects"
@@ -2806,7 +2793,7 @@
 #: src/zope/app/module/browser/add_module.pt:8
 #: src/zope/app/module/browser/edit_module.pt:8
 msgid "Enter the module source code."
-msgstr "Geben sie den Quellcode des Moduls ein."
+msgstr "Geben sie den Quelltext des Moduls ein."
 
 #: src/zope/app/module/browser/browse_module.pt:3
 msgid "View Module Names"
@@ -2831,7 +2818,7 @@
 
 #: src/zope/app/onlinehelp/browser/configure.zcml:7
 msgid "Menu for displaying help actions to be performed with popup"
-msgstr "Menü zum Darstellen von Hilfen via eine Popup Fensters"
+msgstr "Menü zum Darstellen von Hilfen via eines Popup Fensters"
 
 #: src/zope/app/onlinehelp/browser/contexthelp.pt:11
 #: src/zope/app/onlinehelp/browser/helptopic.pt:11
@@ -2840,7 +2827,7 @@
 
 #: src/zope/app/onlinehelp/configure.zcml:55
 msgid "Zope UI Help"
-msgstr "Zope-Oberflächenhilfe"
+msgstr "Zope-Bedienungshilfe"
 
 #: src/zope/app/onlinehelp/configure.zcml:62
 msgid "Welcome"
@@ -2867,11 +2854,11 @@
 #: src/zope/app/workflow/stateful/browser/addtransition.pt:12
 #: src/zope/app/workflow/stateful/browser/addstate.pt:12
 msgid "Id"
-msgstr "Id"
+msgstr "ID"
 
 #: src/zope/app/onlinehelp/interfaces.py:49
 msgid "The Id of this Help Topic"
-msgstr "Die Id dieses Hilfthemas"
+msgstr "Die ID dieses Hilfethemas"
 
 #: src/zope/app/onlinehelp/interfaces.py:54
 msgid "Parent Path"
@@ -2879,19 +2866,19 @@
 
 #: src/zope/app/onlinehelp/interfaces.py:55
 msgid "The Path to the Parent of this Help Topic"
-msgstr "Der Pfad zum Elternelement des Hilfthemas"
+msgstr "Der Pfad zum Elternelement des Hilfethemas"
 
 #: src/zope/app/onlinehelp/interfaces.py:60
 msgid "Help Topic Title"
-msgstr "Titel des Hilfthemas"
+msgstr "Titel des Hilfethemas"
 
 #: src/zope/app/onlinehelp/interfaces.py:61
 msgid "The Title of a Help Topic"
-msgstr "Der Titel des Hilfthemas"
+msgstr "Der Titel des Hilfethemas"
 
 #: src/zope/app/onlinehelp/interfaces.py:62
 msgid "Help Topic"
-msgstr "Hilfthema"
+msgstr "Hilfethema"
 
 #: src/zope/app/onlinehelp/interfaces.py:66
 msgid "Source Text"
@@ -2907,7 +2894,7 @@
 
 #: src/zope/app/onlinehelp/interfaces.py:74
 msgid "The Path to the Definition of a Help Topic"
-msgstr "Der Pfad zur Definition des Hilfthemas"
+msgstr "Der Pfad zur Definition des Hilfethemas"
 
 #: src/zope/app/onlinehelp/interfaces.py:79
 msgid "Source Type"
@@ -2915,15 +2902,15 @@
 
 #: src/zope/app/onlinehelp/interfaces.py:80
 msgid "Type of the source text, e.g. structured text"
-msgstr "Typ des Quelltextes, zum Beispiel \"Structured Text\""
+msgstr "Typ des Quelltextes, zum Beispiel \"structured text\""
 
 #: src/zope/app/onlinehelp/interfaces.py:86
 msgid "Object Interface"
-msgstr "Objekt-Interface"
+msgstr "Objekt-Schnittstelle"
 
 #: src/zope/app/onlinehelp/interfaces.py:87
 msgid "Interface for which this Help Topic is registered."
-msgstr "Interface, für welches dieses Hilfethema registriert ist"
+msgstr "Schnittstelle, für welche dieses Hilfethema registriert ist"
 
 #: src/zope/app/onlinehelp/interfaces.py:92
 msgid "View Name"
@@ -2938,9 +2925,8 @@
 msgstr ""
 
 #: src/zope/app/pagelet/exceptions.py:37
-#, fuzzy
 msgid "IPageletSlot interface not provided."
-msgstr "Das bereitgestellte Interface"
+msgstr ""
 
 #: src/zope/app/pagelet/interfaces.py:150
 msgid "Pagelets registred for context, request, view and slot."
@@ -2951,9 +2937,8 @@
 msgstr ""
 
 #: src/zope/app/pagelet/interfaces.py:185
-#, fuzzy
 msgid "Page data adapter registred for context, request and view."
-msgstr "Es gibt keine registrierten Adapter für dieses Interface."
+msgstr "Es gibt keinen registrierten Adapter."
 
 #: src/zope/app/pagelet/interfaces.py:58
 msgid "weight"
@@ -3042,9 +3027,8 @@
 msgstr "Eine persistente Übersetzungsdomäne"
 
 #: src/zope/app/pas/browser/configure.zcml:21
-#, fuzzy
 msgid "Principal Folder"
-msgstr "Minimaler Ordner"
+msgstr ""
 
 #: src/zope/app/pas/browser/configure.zcml:29
 #, fuzzy
@@ -3184,8 +3168,7 @@
 #: src/zope/app/pas/principalfolder.py:39
 #, fuzzy
 msgid "The Login/Username of the principal. This value can change."
-msgstr ""
-"Eine Anmeldung (Benutzername) fuer den Nutzer. Dieser Wert kann sich ändern."
+msgstr "Eine Anmeldung (Benutzername) fuer den Nutzer. Dieser Wert kann sich ändern."
 
 #: src/zope/app/pas/principalfolder.py:45
 #, fuzzy
@@ -3281,8 +3264,7 @@
 
 #: src/zope/app/pluggableauth/interfaces.py:33
 msgid "The Login/Username of the user. This value can change."
-msgstr ""
-"Eine Anmeldung (Benutzername) fuer den Nutzer. Dieser Wert kann sich ändern."
+msgstr "Eine Anmeldung (Benutzername) fuer den Nutzer. Dieser Wert kann sich ändern."
 
 #: src/zope/app/pluggableauth/interfaces.py:39
 msgid "The password for the user."
@@ -3290,7 +3272,7 @@
 
 #: src/zope/app/presentation/browser/configure.zcml:11
 msgid "Register a view page"
-msgstr "Eine neue Seite registrieren"
+msgstr "Eine neue Ansichtsseite registrieren"
 
 #: src/zope/app/presentation/browser/configure.zcml:3
 msgid "Change page"
@@ -3321,16 +3303,16 @@
 #: src/zope/app/presentation/pagefolder.py:57
 #: src/zope/app/presentation/presentation.py:93
 msgid "The interface of the objects being viewed"
-msgstr "Das Interface der Objekte welches angesehen wird"
+msgstr "Die Schnittstelle der anzuzeigenden Objekte"
 
 #: src/zope/app/presentation/pagefolder.py:63
 msgid "The dotted name of a factory for creating the view"
-msgstr "Der Name der zur Erzeugung notwendigen Fabrik einer Ansicht"
+msgstr "Der gepunktete Name der zur Erzeugung notwendigen Fabrik einer Ansicht"
 
 #: src/zope/app/presentation/pagefolder.py:69
 #: src/zope/app/presentation/presentation.py:109
 msgid "The skin layer the view is registered for"
-msgstr "Die Themenebene, für welche die Ansicht registriert ist"
+msgstr "Die Anzeigeform-Ebene, für welche die Ansicht registriert ist"
 
 #: src/zope/app/presentation/pagefolder.py:77
 msgid "The permission required to use the view"
@@ -3346,7 +3328,7 @@
 
 #: src/zope/app/presentation/presentation.py:101
 msgid "The type of requests the view works with"
-msgstr "Der Typ der Anfrage mit welcher die Ansicht arbeitet"
+msgstr "Der Typ der Anfrage, mit welcher die Ansicht arbeitet"
 
 #: src/zope/app/presentation/presentation.py:123
 msgid "view-component"
@@ -3374,7 +3356,7 @@
 
 #: src/zope/app/presentation/presentation.py:182
 msgid "Factory to be called to construct an adapter"
-msgstr "Fabrik die zur Erzeugung des Adapters aufgerufen wird"
+msgstr "Fabrik, die zur Erzeugung des Adapters aufgerufen wird"
 
 #: src/zope/app/presentation/presentation.py:198
 msgid "page-component"
@@ -3399,7 +3381,7 @@
 
 #: src/zope/app/presentation/zpt.zcml:10
 msgid "Persistent View Page Template"
-msgstr "Persistente Ansichts Page Template"
+msgstr "Persistente Ansichts Seitenschablone"
 
 #: src/zope/app/presentation/zpt.zcml:10
 msgid "zope.app.ZPTTemplate"
@@ -3407,11 +3389,11 @@
 
 #: src/zope/app/principalannotation/configure.zcml:22
 msgid "Stores Annotations for Principals"
-msgstr "Speichert Anmerkungen für Prinzipal"
+msgstr "Speichert Anmerkungen für Nutzungsberechtigte"
 
 #: src/zope/app/principalannotation/configure.zcml:22
 msgid "Principal Annotation Service"
-msgstr "Prinzipal-Anmerkungsdienst"
+msgstr "Nutzungberechtigter-Anmerkungsdienst"
 
 #: src/zope/app/publisher/interfaces/browser.py:49
 #, fuzzy
@@ -3424,15 +3406,16 @@
 msgstr "Der Text, der für den Menüeintrag angezeigt werden soll"
 
 #: src/zope/app/publisher/interfaces/browser.py:55
-#, fuzzy
 msgid "Menu item description"
-msgstr "Bar Beschreibung"
+msgstr "Beschreibung zum Menüeintrag"
 
 #: src/zope/app/publisher/interfaces/browser.py:56
 msgid ""
 "A description of the menu item. This might be shown on menu pages or in pop-"
 "up help for menu items."
 msgstr ""
+"Eine Beschreibung für den Menüeintrag. Sie kann auf Menüseiten oder "
+"in Pop-up-Hilfefenstern angezeigt werden."
 
 #: src/zope/app/publisher/interfaces/browser.py:62
 #, fuzzy
@@ -3445,16 +3428,23 @@
 "displayed. The action is usually given as a relative URL, relative to the "
 "object the menu item is for."
 msgstr ""
+"Wenn der Benutzer einen Menüeintrag im Browser auswählt, wird die "
+"in der Aktion angegebene URL aufgerufen. Dabei wird üblicherweise eine "
+"relative URL angegeben, relativ zu dem Objekt, für das der Menüeintrag "
+"vorhanden ist."
 
 #: src/zope/app/publisher/interfaces/browser.py:71
 msgid "Menu item ordering hint"
-msgstr ""
+msgstr "Hinweis zum Ordnen des Menüeintrags"
 
 #: src/zope/app/publisher/interfaces/browser.py:72
 msgid ""
 "This attribute provides a hint for menu item ordering.Menu items will "
 "generally be sorted by the `for_`attribute and then by the order."
 msgstr ""
+"Dieses Attribut enthält einen Hinweis zum Einordnen des Menüeintrags. Im "
+"allgemeinen werden Menüeinträge nach dem '_for'-Attribut und danach "
+"'order'-Attribut geordnet."
 
 #: src/zope/app/publisher/interfaces/browser.py:78
 msgid "A condition for displaying the menu item"
@@ -3486,22 +3476,20 @@
 "Filter einen unwahren Wert zurückgibt."
 
 #: src/zope/app/publisher/interfaces/browser.py:94
-#, fuzzy
 msgid "Icon URI"
-msgstr "Verbindungen"
+msgstr ""
 
 #: src/zope/app/publisher/interfaces/browser.py:95
-#, fuzzy
 msgid "URI of the icon representing this menu item"
-msgstr "Eine Bedingung zum Darstellen des Menüeintrags"
+msgstr "URI des Icon zum Darstellen des Menüeintrags"
 
 #: src/zope/app/pythonpage/__init__.py:41
 msgid "The source of the Python page."
-msgstr "Der Quellcode der Python-Seite."
+msgstr "Der Quelltext der Python-Seite."
 
 #: src/zope/app/pythonpage/__init__.py:46
 msgid "The content type the script outputs."
-msgstr "Der Typ des Inhalts, den das Skript ausgiebt."
+msgstr "Der Typ des Inhalts, den das Skript ausgibt."
 
 #: src/zope/app/pythonpage/browser.py:43
 msgid "A syntax error occured."
@@ -3547,10 +3535,9 @@
 msgstr "Datenbankverbindungs-Registrierung hinzufügen"
 
 #: src/zope/app/rdb/browser/configure.zcml:5
-msgid ""
-"Database Adapters are used to connect to external       relational databases."
+msgid "Database Adapters are used to connect to external       relational databases."
 msgstr ""
-"Datenbankadapter werde benutzt, um Verbindungen zu externen relationalen "
+"Datenbankadapter werden benutzt, um Verbindungen zu externen relationalen "
 "Datenbanken herzustellen."
 
 #: src/zope/app/rdb/browser/configure.zcml:5
@@ -3600,8 +3587,7 @@
 
 #: src/zope/app/rdb/browser/rdbtestsql.pt:13
 msgid "Here you can enter an SQL statement, so you can test the connection."
-msgstr ""
-"Sie können hier eine SQL-Abfrage eingeben, um die Verbindung zu testen."
+msgstr "Sie können hier eine SQL-Abfrage eingeben, um die Verbindung zu testen."
 
 #: src/zope/app/rdb/browser/rdbtestsql.pt:18
 msgid "Query"
@@ -3671,7 +3657,7 @@
 
 #: src/zope/app/registration/browser/editregistration.pt:37
 msgid "(disabled)"
-msgstr "Deaktiviert"
+msgstr "(Deaktiviert)"
 
 #: src/zope/app/registration/browser/editregistration.pt:56
 msgid "top-button"
@@ -3744,8 +3730,8 @@
 "The path to the component; this may be absolute, or relative to the nearest "
 "site management folder"
 msgstr ""
-"Der Pfad zu der Komponente; dieser kann absolut oder relative zu dem "
-"nächsten Webseiten-Verwaltungs-Ordner"
+"Der Pfad zu der Komponente; dieser kann absolut oder relativ zu dem "
+"naheliegendsten Webplatz-Verwaltungsordner"
 
 #: src/zope/app/registration/interfaces.py:125
 msgid "The permission needed to use the component"
@@ -3753,7 +3739,7 @@
 
 #: src/zope/app/registration/interfaces.py:137
 msgid "the component named in the registration"
-msgstr "die Komponente die in der Registrierung benannt wurde"
+msgstr "Die Komponente, die in der Registrierung benannt wurde"
 
 #: src/zope/app/registration/interfaces.py:30
 msgid "Unregistered"
@@ -3832,7 +3818,7 @@
 
 #: src/zope/app/schema/browser/__init__.py:52
 msgid "Must select a field to delete"
-msgstr "Zum löschen müssen Sie ein Feld auswählen"
+msgstr "Zum Löschen müssen Sie ein Feld auswählen"
 
 #: src/zope/app/schema/browser/__init__.py:63
 msgid "Invalid field name: %s"
@@ -3853,8 +3839,8 @@
 #: src/zope/app/schema/browser/configure.zcml:5
 msgid "These are schemas that live in the ZODB and are modifiable."
 msgstr ""
-"Es handelt sich um Schemas, die in der ZODB leben und verändert werden "
-"können."
+"Es handelt sich um Schemas, die in der ZODB leben und die verändert "
+"werden können."
 
 #: src/zope/app/schema/browser/configure.zcml:5
 msgid "Persistent, Local Schemas"
@@ -3916,19 +3902,19 @@
 
 #: src/zope/app/schema/fieldforms.zcml:33
 msgid "TextLine Field"
-msgstr "Textzeilenfeld"
+msgstr "Feld für Textzeile"
 
 #: src/zope/app/schema/fieldforms.zcml:33
 msgid "A TextLine Field"
-msgstr "Ein Textzeilenfeld"
+msgstr "Ein Feld für eine Textzeile"
 
 #: src/zope/app/schema/fieldforms.zcml:33
 msgid "Add TextLine Field"
-msgstr "Textzeilenfeld hinzufügen"
+msgstr "Feld für Textzeile hinzufügen"
 
 #: src/zope/app/schema/fieldforms.zcml:47
 msgid "Edit TextLine Field"
-msgstr "Textzeilenfeld bearbeiten"
+msgstr "Feld für Textzeile bearbeiten"
 
 #: src/zope/app/schema/fieldforms.zcml:59
 msgid "Add Boolean Field"
@@ -3964,7 +3950,7 @@
 
 #: src/zope/app/schema/fields.zcml:102
 msgid "BytesLine Field"
-msgstr "Byteszeilenfeld"
+msgstr "Feld für Byteszeile"
 
 #: src/zope/app/schema/fields.zcml:114 src/zope/app/schema/fieldforms.zcml:7
 msgid "Text Field"
@@ -3972,7 +3958,7 @@
 
 #: src/zope/app/schema/fields.zcml:128
 msgid "Text Line Field"
-msgstr "Textzeilenfeld"
+msgstr "Feld Textzeile"
 
 #: src/zope/app/schema/fields.zcml:140 src/zope/app/schema/fieldforms.zcml:59
 msgid "Boolean Field"
@@ -4028,7 +4014,7 @@
 
 #: src/zope/app/schema/fields.zcml:293
 msgid "Interface Field"
-msgstr "Interface-Feld"
+msgstr "Schnittstellen-Feld"
 
 #: src/zope/app/schema/fields.zcml:38
 msgid "Container Field"
@@ -4036,7 +4022,7 @@
 
 #: src/zope/app/schema/fields.zcml:49
 msgid "Iterable Field"
-msgstr "Wiederholendes Feld"
+msgstr "Durchlaufbares Feld"
 
 #: src/zope/app/schema/fields.zcml:5
 msgid "Basic Field"
@@ -4048,7 +4034,7 @@
 
 #: src/zope/app/schema/fields.zcml:75
 msgid "MinMaxLen Field"
-msgstr "MinMaxLen-Feld"
+msgstr "MinMaxLängen-Feld"
 
 #: src/zope/app/schema/fields.zcml:90
 msgid "Bytes Field"
@@ -4109,11 +4095,11 @@
 #: src/zope/app/schemacontent/interfaces.py:38
 #: src/zope/app/introspector/introspector.pt:31
 msgid "interface-component"
-msgstr "Interface"
+msgstr "Schnittstelle"
 
 #: src/zope/app/schemacontent/interfaces.py:39
 msgid "Specifies the interface this menu item is for."
-msgstr "Gibt das Interface an, für welches dieser Menüeintrag gilt."
+msgstr "Gibt die Schnittstelle an, für welches dieser Menüeintrag gilt."
 
 #: src/zope/app/schemacontent/interfaces.py:45
 msgid "Menu Id"
@@ -4135,22 +4121,22 @@
 "specifed id. If no menu was found or the menu is a global menu, then an "
 "error is created."
 msgstr ""
-"Wenn dies auf True (wahr) gesetzt wird, wird das System einen lokalen "
+"Wenn dies auf True (wahr) gesetzt ist, wird das System einen lokalen "
 "Browsermenüdienst und ein lokales Browsermenü für Sie erstellen. Falls False "
-"(falsch, unwahr) angegeben wird, wird das System versuchen, den nächsten "
+"(falsch, unwahr) angegeben ist, wird das System versuchen, den nächsten "
 "lokalen Browsermenüdienst mit der angegebenen ID zu finden. Falls kein Menü "
-"gefunden werde kann oder das Menü ein globales Menü sein sollte, wird ein "
+"gefunden werden kann oder das Menü ein globales Menü sein sollte, wird ein "
 "Fehler ausgegeben."
 
 #: src/zope/app/schemacontent/interfaces.py:73
 #: src/zope/app/schemacontent/interfaces.py:105
 msgid "Name of Content Component Type"
-msgstr "Name des Inhaltskomponenten-Typ"
+msgstr "Name des Inhaltskomponenten-Typs"
 
 #: src/zope/app/schemacontent/interfaces.py:74
 #: src/zope/app/schemacontent/interfaces.py:106
 msgid "This is the name of the document type."
-msgstr "Name des Dokumenttypen."
+msgstr "Name des Dokumenttyps."
 
 #: src/zope/app/schemacontent/interfaces.py:78
 #: src/zope/app/schemacontent/interfaces.py:110
@@ -4175,10 +4161,10 @@
 "mutable schema evolves. If the value is False, then the Content Component's "
 "can change (which is desirable in some cases - i.e. during development.)"
 msgstr ""
-"Falls dieses Feld auf Wahr gesetzt wird, wird eine Kopie des Schemas in der "
+"Falls dieses Feld auf Wahr gesetzt ist, wird eine Kopie des Schemas in der "
 "Instanz der Inhaltskomponente verwendet. Dies hat den Vorteil, dass das "
 "Schema einer bereits existierenden Inhaltskomponente in Stein gemeißelt ist "
-"und sich niemals ändern kann, selbst wenn das Schema verändernt wird. Falls "
+"und sich niemals ändern kann, selbst wenn das Schema verändert wird. Falls "
 "der Wert Falsch ist, dann können sich Inhaltskomponenten ändern (was "
 "manchmal erwünscht ist, z.B. während der Entwicklung)"
 
@@ -4201,8 +4187,7 @@
 
 #: src/zope/app/security/browser/login_failed.pt:9
 #, fuzzy
-msgid ""
-"You cancelled the login procedure. <a href=\"XXX\">Click here to return.</a>"
+msgid "You cancelled the login procedure. <a href=\"XXX\">Click here to return.</a>"
 msgstr ""
 "Sie haben den Loginprozess abgebrochen. <a href=\"\"> Bitte hier klicken um "
 "zurückzukehren. </a>"
@@ -4262,7 +4247,7 @@
 # Default: "Manage Code"
 #: src/zope/app/security/configure.zcml:71
 msgid "manage-code-permission"
-msgstr "Quellcode verwalten"
+msgstr "Quelltext verwalten"
 
 # Default: "Manage Services"
 #: src/zope/app/security/configure.zcml:77
@@ -4272,13 +4257,13 @@
 # Default: "Manage Services"
 #: src/zope/app/security/configure.zcml:82
 msgid "manage-principal-permission"
-msgstr "Dienste verwalten"
+msgstr "Nutzungsberechtigungen verwalten"
 
 #: src/zope/app/security/configure.zcml:87
 msgid ""
 "Manage the Zope Application, such as Restart/Shutdown or                    "
 "packing the ZODB."
-msgstr "Zope-Anwedung verwalten (z.B. neustarten/runterfahren/ZODB packen)"
+msgstr "Zope-Anwendung verwalten (z.B. Neustarten/Herunterfahren/ZODB packen)"
 
 #: src/zope/app/security/configure.zcml:87
 msgid "manage-application-permission"
@@ -4302,7 +4287,7 @@
 "principals."
 msgstr ""
 "Rollen werden dazu benutzt, Erlaubnisse zu kombinieren, und können "
-"Prinzipalen zugewiesen werden."
+"Nutzungsberechtigten zugewiesen werden."
 
 #: src/zope/app/securitypolicy/browser/configure.zcml:6
 #: src/zope/app/securitypolicy/browser/configure.zcml:36
@@ -4311,9 +4296,8 @@
 msgstr "Rolle"
 
 #: src/zope/app/securitypolicy/browser/configure.zcml:68
-#, fuzzy
 msgid "Role-Permissions"
-msgstr "Berechtigungen:"
+msgstr "Rollen-Berechtigungen:"
 
 #: src/zope/app/securitypolicy/browser/configure.zcml:90
 msgid "Grant"
@@ -4325,17 +4309,15 @@
 
 #: src/zope/app/securitypolicy/browser/grant.pt:18
 msgid "Grant roles to principals"
-msgstr "Prinzipal Erlaubnisse gewähren"
+msgstr "Nutzungsberechtigten Erlaubnisse gewähren"
 
 #: src/zope/app/securitypolicy/browser/granting.pt:13
-#, fuzzy
 msgid "Select a principal:"
-msgstr "Sprachen auswählen:"
+msgstr "Nutzungsberechtigten auswählen:"
 
 #: src/zope/app/securitypolicy/browser/granting.pt:18
-#, fuzzy
 msgid "Grants for the selected principal"
-msgstr "Prinzipal Erlaubnisse gewähren"
+msgstr "Erlaubnisse für ausgesuchten Nutzungsberechtigten gewähren"
 
 #: src/zope/app/securitypolicy/browser/granting.pt:20
 #: src/zope/app/securitypolicy/browser/granting.pt:56
@@ -4344,27 +4326,24 @@
 msgstr "Gewähren"
 
 #: src/zope/app/securitypolicy/browser/granting.pt:25
-#, fuzzy
 msgid "Roles:"
-msgstr "Rollen"
+msgstr "Rollen:"
 
 #: src/zope/app/securitypolicy/browser/granting.pt:5
-#, fuzzy
 msgid "Granting Roles and Permissions to Principals"
-msgstr "Prinzipal Erlaubnisse gewähren"
+msgstr "Nutzungsberechtigten Rollen zuweisen und  Erlaubnisse gewähren"
 
 #: src/zope/app/securitypolicy/browser/granting.py:34
 msgid "Allow"
-msgstr ""
+msgstr "Zulassen"
 
 #: src/zope/app/securitypolicy/browser/granting.py:35
-#, fuzzy
 msgid "Unset"
-msgstr "Benutzer"
+msgstr ""
 
 #: src/zope/app/securitypolicy/browser/granting.py:36
 msgid "Deny"
-msgstr ""
+msgstr "Verweigern"
 
 #: src/zope/app/securitypolicy/browser/manage_access.pt:33
 msgid "Roles"
@@ -4393,15 +4372,15 @@
 "the Allow or Deny lists. Make sure you don't select the same permission in "
 "both lists though."
 msgstr ""
-"Diese Seite zeigt die Genehmigungen die der Rolle ${role_title} (Id: "
-"${role_id}) erlaubt oder verweigert wurden. Um dies zu ändern, wählen sie "
-"einfach einige Genehmigungen in den Erlauben und Verweigern Liste. Stellen "
-"Sie jedoch sicher, daß sie nicht die gleiche Genehmigung in beiden Listen "
-"gleichzeitig selektieren."
+"Diese Seite zeigt die Berechtigungen, die der Rolle ${role_title} (Id: "
+"${role_id}) erlaubt oder verweigert wurden. Um Einstellungen zu ändern, "
+"wählen sie einfach Berechtigungen in den 'Erlauben'- und 'Verweigern'-Liste. "
+"Stellen Sie jedoch sicher, daß sie nicht die gleiche Berechtigung in beiden "
+"Listen auswählen."
 
 #: src/zope/app/securitypolicy/browser/rolepermissionview.py:155
 msgid "Settings changed at ${date_time}"
-msgstr "Daten am ${date_time} geändert"
+msgstr "Einstellungen am ${date_time} geändert"
 
 #: src/zope/app/securitypolicy/browser/rolepermissionview.py:59
 msgid "permission-acquire"
@@ -4421,15 +4400,15 @@
 
 #: src/zope/app/securitypolicy/configure.zcml:88
 msgid "Everybody"
-msgstr "Alle"
+msgstr "Jeder"
 
 #: src/zope/app/securitypolicy/configure.zcml:90
 msgid "Site Manager"
-msgstr "Webseiten-Verwalter"
+msgstr "Webplatz-Verwalter"
 
 #: src/zope/app/securitypolicy/configure.zcml:91
 msgid "Site Member"
-msgstr "Webseiten-Mitglied"
+msgstr "Webplatz-Mitglied"
 
 #: src/zope/app/session/browser.zcml:15
 msgid "Cookie Client Id Manager Properties"
@@ -4501,8 +4480,8 @@
 "Approximate epoch time this ISessionData was last retrieved from its "
 "ISessionDataContainer"
 msgstr ""
-"Ungefähre Epoch-Zeit, seitdem der ISessionDataContainer zuletzt auf dieses "
-"ISessionData zugegriffen hat."
+"Ungefähre Epochen-Zeit, zu der der ISessionDataContainer zuletzt auf "
+"dieses ISessionData zugegriffen hat."
 
 #: src/zope/app/session/interfaces.py:66
 msgid "Timeout"
@@ -4513,12 +4492,12 @@
 "Number of seconds before data becomes stale and may be removed. A value of "
 "'0' means no expiration."
 msgstr ""
-"Anzahl von Sekunden bis die Daten verfallen und gelöscht werden können. Ein "
+"Anzahl von Sekunden, bis die Daten verfallen und gelöscht werden können. Ein "
 "Wert von '0' bedeutet keinen Verfall."
 
 #: src/zope/app/session/interfaces.py:75
 msgid "Timeout resolution (in seconds)"
-msgstr "Timeout-Auflösung (in Sekunden)"
+msgstr "Auszeit-Auflösung (in Sekunden)"
 
 #: src/zope/app/session/interfaces.py:76
 msgid ""
@@ -4527,7 +4506,7 @@
 "items to time out later than the 'Data object timeout value' by  a factor of "
 "(at most) this many seconds."
 msgstr ""
-"Definiert die 'Auflösung' des Timeouts. Wenn man diesen Wert höher setzt, "
+"Definiert die 'Auflösung' der Auszeit. Wenn man diesen Wert höher setzt, "
 "dann muss die Vergänglichkeitmaschinerie weniger 'schreiben' zu Kosten das "
 "die Objekte später verfallen als der 'Datenobjekt Timeout Wert' mit einem "
 "Faktor von (am meisten) so vielen Sekunden."
@@ -4581,7 +4560,7 @@
 
 #: src/zope/app/site/browser/__init__.py:414
 msgid "Invalid service type specified"
-msgstr "Ungültiger Diensttyp angegeben"
+msgstr "Ungültiger Dienstetyp angegeben"
 
 #: src/zope/app/site/browser/__init__.py:421
 msgid "No change"
@@ -4612,7 +4591,7 @@
 
 #: src/zope/app/site/browser/configure.zcml:103
 msgid "Interface Browse"
-msgstr "Interface Ãœbersicht"
+msgstr "Schnittstellen-Ãœbersicht"
 
 #: src/zope/app/site/browser/configure.zcml:138
 msgid "Visit default folder"
@@ -4628,7 +4607,7 @@
 
 #: src/zope/app/site/browser/configure.zcml:163
 msgid "Add Site Management Folder"
-msgstr "Webseitenverwaltungsordner hinzufügen"
+msgstr "Webplatzverwaltungsordner hinzufügen"
 
 #: src/zope/app/site/browser/configure.zcml:186
 msgid "Edit Service Registration"
@@ -4636,7 +4615,7 @@
 
 #: src/zope/app/site/browser/configure.zcml:210
 msgid "Takes you to a menu of services to add"
-msgstr "Bringt sie zu einem Menü zum hinzufügen von Diensten"
+msgstr "Bringt Sie zu einem Menü zum Hinzufügen von Diensten"
 
 #: src/zope/app/site/browser/configure.zcml:210
 #: src/zope/app/site/browser/serviceactivation.pt:26
@@ -4646,11 +4625,11 @@
 
 #: src/zope/app/site/browser/configure.zcml:232
 msgid "Service Tools"
-msgstr "Dienstwerkzeuge"
+msgstr "Dienste-Werkzeuge"
 
 #: src/zope/app/site/browser/configure.zcml:232
 msgid "Service tool management."
-msgstr "Dienstwerkzeug-Verwaltung"
+msgstr "Dienstewerkzeug-Verwaltung"
 
 #: src/zope/app/site/browser/configure.zcml:237
 #: src/zope/app/site/browser/configure.zcml:246
@@ -4660,15 +4639,15 @@
 
 #: src/zope/app/site/browser/configure.zcml:60
 msgid "Make a site"
-msgstr "Webseite erstellen"
+msgstr "Webplatz erstellen"
 
 #: src/zope/app/site/browser/configure.zcml:69
 msgid "Manage Site"
-msgstr "Webseite verwalten"
+msgstr "Webplatz verwalten"
 
 #: src/zope/app/site/browser/configure.zcml:7
 msgid "Site-Management Folder"
-msgstr "Webseitenverwaltungsordner"
+msgstr "Webplatzverwaltungsordner"
 
 #: src/zope/app/site/browser/configure.zcml:79
 msgid "Tasks"
@@ -4676,11 +4655,11 @@
 
 #: src/zope/app/site/browser/interfacebrowse.pt:10
 msgid "Interface Name"
-msgstr "Interface-Name"
+msgstr "Schnittstellen-Name"
 
 #: src/zope/app/site/browser/interfacebrowse.pt:5
 msgid "Interfaces registered with the Utility service"
-msgstr "Interfaces die mit dem Werkzeugdienst registriert sind"
+msgstr "Schnittstellen, die mit dem Werkzeugdienst registriert sind"
 
 #: src/zope/app/site/browser/interfacedetail.pt:11
 msgid "Documentation"
@@ -4704,11 +4683,11 @@
 
 #: src/zope/app/site/browser/interfacedetail.pt:67
 msgid "* indicates required fields."
-msgstr "* zeigt ein erfordertes Feld an."
+msgstr "* zeigt ein erforderliches Feld an."
 
 #: src/zope/app/site/browser/interfacedetail.pt:7
 msgid "Interface ${iface_name}"
-msgstr "Interface ${iface_name}"
+msgstr "Schnittstelle ${iface_name}"
 
 #: src/zope/app/site/browser/interfacedetail.pt:72
 msgid "Registrations for ${service_name} service"
@@ -4753,14 +4732,14 @@
 "The (change registration) link allows activating a different implementation "
 "or disabling the service altogether."
 msgstr ""
-"Es sei denn ein Dienst ist deaktiviert, der Name des Dienstes bietet eine "
-"Link zu dem aktiven Dienst. Der (Registrierung ändern) Link erlaubt das "
+"Wenn der Dienst nicht deaktiviert ist, verbindet der Dienste-Name "
+"zu dem aktiven Dienst. Der (Registrierung ändern)-Link erlaubt das "
 "Aktivieren einer anderen Implementation oder sogar das Abschalten des "
 "Dienstes."
 
 #: src/zope/app/site/browser/services.pt:5
 msgid "Services registered in this site manager"
-msgstr "Dienste die mit diesem Seitenverwalter registriert sind"
+msgstr "Dienste, die für diesen Webplatzverwalter registriert sind"
 
 #: src/zope/app/site/browser/services.pt:54
 msgid "(change registration)"
@@ -4779,12 +4758,14 @@
 "this site or provide new serivces and utilities (which may override existing "
 "tools)."
 msgstr ""
-"Tools bestehen aus Diensten und Werkzeugen. Dienste registrieren such mit "
-"dem Dienst-Dienst, während Werkzeuge sich selbst mit dem Werkzeugdienst "
-"registrieren. Diese führen Aufgaben wie Fehlerlogging, Übersetzungen, "
-"Authentifizierung und so weiter aus. Sie können hier entweder existierende "
+"Arbeitsmittel bestehen aus Diensten und Werkzeugen. Dienste registrieren "
+"sich mit dem Dienste-Dienst, während Werkzeuge sich selbst mit dem "
+"Werkzeugdienst registrieren. Arbeitsmittel führen Aufgaben wie "
+"Fehlerlogging, Ãœbersetzungen, Authentifizierung und so weiter aus. "
+"\n\n"
+"Sie können hier entweder existierende "
 "Dienste und Werkzeuge konfigurieren oder neue Dienste und Werkzeuge "
-"bereitstellen (welche eventuell existierende Tools aufheben)."
+"bereitstellen (welche eventuell existierende Arbeitsmittel aufheben)."
 
 # Default: "Configure services"
 #: src/zope/app/site/browser/tasks.pt:30 src/zope/app/site/browser/tasks.pt:35
@@ -4794,7 +4775,7 @@
 # Default: "Configure services"
 #: src/zope/app/site/browser/tasks.pt:41
 msgid "label-configure-utilities"
-msgstr "Dienste konfigurieren"
+msgstr "Werkzeuge konfigurieren"
 
 #: src/zope/app/site/browser/tasks.pt:49
 msgid "label-software"
@@ -4802,7 +4783,7 @@
 
 #: src/zope/app/site/browser/tasks.pt:5
 msgid "heading-common-site-management-tasks"
-msgstr "Häufige Webseitenverwaltungsaufgaben"
+msgstr "Häufige Webplatzverwaltungsaufgaben"
 
 #: src/zope/app/site/browser/tasks.pt:52
 msgid ""
@@ -4810,9 +4791,10 @@
 "The first step in creating a new software package is to create a new Site "
 "Management Folder to contain the software."
 msgstr ""
-"Diese Webseite kann das Verhalten von bestehender Software anpassen oder ein "
+"Dieser Webplatz kann das Verhalten von bestehender Software anpassen "
+"oder ein "
 "eigenes Verhalten definieren. Der erste Schritt beim Erstellen eines neuen "
-"Softwarepakets is das erstellen eines Webseitenverwaltungsordners, der die "
+"Softwarepakets is das Erstellen eines Webplatzverwaltungsordners, der die "
 "Software enthält."
 
 #: src/zope/app/site/browser/tasks.pt:61
@@ -4822,15 +4804,16 @@
 # Default: "Create a new Site Management Folder"
 #: src/zope/app/site/browser/tasks.pt:68
 msgid "label-create-new-site-management-folder"
-msgstr "Neuen Webseitenverwaltungsordner erstellen"
+msgstr "Neuen Webplatzverwaltungsordner erstellen"
 
 #: src/zope/app/site/browser/tasks.pt:9
 msgid ""
 "The site management interface allows you to setup and configure software for "
 "this site."
 msgstr ""
-"Die Webseitenverwaltungs-Oberfläche erlaubt es, Software dieser Webseite zu "
-"installieren und konfigurieren."
+"Die Webplatzverwaltungs-Oberfläche erlaubt es, Software dieses "
+"Webplatzes zu "
+"installieren und zu konfigurieren."
 
 #: src/zope/app/site/browser/tool.pt:101
 msgid "rename-button"
@@ -4851,8 +4834,8 @@
 #: src/zope/app/site/browser/tool.pt:29
 msgid "Unless a tool is disabled the tool name links to the active tool. ..."
 msgstr ""
-"Der Werkzeugname verweist auf das aktive Werkzeug, es sei denn das Werkzeug "
-"ist deaktiviert "
+"Wenn das Werkzeug nicht deaktiviert ist, verbindet der Werkzeugname "
+"mit dem aktiven Werkzeug."
 
 #: src/zope/app/site/browser/tool.pt:41
 msgid "Parent"
@@ -4883,11 +4866,11 @@
 
 #: src/zope/app/site/browser/tools.py:110
 msgid "Deleted selected tools."
-msgstr "Ausgewählte Tools wurden gelöscht."
+msgstr "Ausgewählte Werkzeuge wurden gelöscht."
 
 #: src/zope/app/site/browser/tools.py:115
 msgid "Renamed selected tools."
-msgstr "Ausgewählte Tools umbenannt."
+msgstr "Ausgewählte Werkzeuge umbenannt."
 
 #: src/zope/app/site/browser/tools.py:118
 msgid "Activated registrations."
@@ -4899,11 +4882,11 @@
 
 #: src/zope/app/site/interfaces.py:161 src/zope/app/utility/interfaces.py:42
 msgid "The name that is registered"
-msgstr "Der Name der registriert ist"
+msgstr "Der registrierte Name"
 
 #: src/zope/app/size/__init__.py:42
 msgid "not-available"
-msgstr "-"
+msgstr "nicht verfügbar"
 
 #: src/zope/app/size/__init__.py:46
 msgid "0 KB"
@@ -4936,7 +4919,7 @@
 
 #: src/zope/app/sqlscript/browser/edit.pt:11
 msgid "change-and-test"
-msgstr "Änderungen Speichern und Testen"
+msgstr "Änderungen speichern und testen"
 
 #: src/zope/app/sqlscript/browser/test.pt:14
 msgid "Argument Name"
@@ -4949,7 +4932,7 @@
 
 #: src/zope/app/sqlscript/browser/test.pt:31
 msgid "test-button"
-msgstr "Test"
+msgstr "Testen"
 
 #: src/zope/app/sqlscript/browser/testresults.pt:28
 msgid "An Error occurred"
@@ -4998,7 +4981,7 @@
 "There isn't enough context to get URL information. This is probably due to a "
 "bug in setting up location information."
 msgstr ""
-"Es gibt nicht genug Kontext um die URL-Informationen abzurufen. Dies ist "
+"Es gibt nicht genug Kontext, um die URL-Informationen abzurufen. Dies ist "
 "wahrscheinlich auf einen Fehler in der Installation von "
 "Lokalisierungsinformationen zurückzuführen."
 
@@ -5028,7 +5011,7 @@
 "With this permission a user may undo all transactions,                    "
 "regardless of who initiated them"
 msgstr ""
-"Mit dieser Erlaubnis darf ein Benutzer alle Transaktionen, gleichgültig wer "
+"Mit dieser Berechtigung darf ein Benutzer alle Transaktionen, gleichgültig wer "
 "sie initiiert hat, rückgängig machen."
 
 #: src/zope/app/undo/configure.zcml:7
@@ -5036,7 +5019,7 @@
 "With this permission a user may undo his/her own                    "
 "transactions."
 msgstr ""
-"Mit dieser Erlaubnis darf ein Benutzer seine eigenen Transaktionen "
+"Mit dieser Berechtigung darf ein Benutzer seine eigenen Transaktionen "
 "rückgängig machen"
 
 # Default: "Manage Content"
@@ -5056,18 +5039,18 @@
 msgstr ""
 "Wählen Sie eine oder mehrere Transaktionen aus der Liste und klicken sie auf "
 "die Schaltfläche unten. Bitte beachten Sie, dass Sie nur Transaktionen "
-"rückgängig machen können, wen n das Objekt seitdem in einer späteren "
+"rückgängig machen können, wenn das Objekt seitdem in einer späteren "
 "Transaktionen weder von Ihnen noch von jemand anderes verändert wurde."
 
 #: src/zope/app/undo/undo_all.pt:7
 msgid "This form lets you undo all transactions initiated by any user."
 msgstr ""
 "Dieses Formular bietet die Möglichkeit, Transaktionen aller Benutzer "
-"rückgängig zumachen"
+"rückgängig zu machen"
 
 #: src/zope/app/undo/undo_macros.pt:101
 msgid "View ${number} earlier transactions"
-msgstr "${number} ehere Transaktionen anzeigen"
+msgstr "${number} frühere Transaktionen anzeigen"
 
 #: src/zope/app/undo/undo_macros.pt:112
 msgid "View ${number} later transactions"
@@ -5105,7 +5088,7 @@
 # Default: "Principal"
 #: src/zope/app/undo/undo_macros.pt:46
 msgid "heading-principal"
-msgstr "Prinzipal"
+msgstr "Nutzungsberechtigter"
 
 #: src/zope/app/undo/undo_macros.pt:47
 msgid "heading-date"
@@ -5131,31 +5114,31 @@
 
 #: src/zope/app/uniqueid/browser/configure.zcml:12
 msgid "A utility that provides unique ids to objects"
-msgstr "Ein Hilfsmittel welches eindeutige Ids für Objekte erstellt."
+msgstr "Ein Werzeug,  welches eindeutige IDs für Objekte erstellt."
 
 #: src/zope/app/uniqueid/browser/configure.zcml:12
 msgid "Unique Id Utility"
-msgstr "Eindeutige-Id Hilfsmittel"
+msgstr "Eindeutige-ID-Werkzeug"
 
 #: src/zope/app/uniqueid/browser/configure.zcml:19
 msgid "Registered Objects"
 msgstr "Registrierte Objekte"
 
 #: src/zope/app/uniqueid/browser/configure.zcml:5
-#, fuzzy
 msgid "Unique Id Tool"
-msgstr "Eindeutige-Id Hilfsmittel"
+msgstr "Eindeutige-ID-Werkzeug"
 
 #: src/zope/app/uniqueid/browser/configure.zcml:5
 msgid ""
 "Unique Ids Tools are used to provide system-wide unique ids       for "
 "documents."
 msgstr ""
+"Das Werkzeug 'Eindeutige IDs' stellt systemweit eindeutige IDs für "
+"Dokumente bereit."
 
 #: src/zope/app/uniqueid/browser/registrations.pt:5
-#, fuzzy
 msgid "XXX objects"
-msgstr "Objekte"
+msgstr "XXX Objekte"
 
 #: src/zope/app/uniqueid/browser/registrations.pt:7
 #: src/zope/app/schema/browser/schema_edit.pt:30
@@ -5182,7 +5165,7 @@
 "button to deactivate"
 msgstr ""
 "Kann aktive Werkzeuge nicht löschen: ${utility_names}; bitte benutzen Sie "
-"Deaktivieren, um die Werkzeuge zu deaktivieren"
+"den Deaktivieren-Knopf, um die Werkzeuge zu deaktivieren"
 
 #: src/zope/app/utility/browser/__init__.py:146
 msgid "Deleted: ${utility_names}"
@@ -5194,13 +5177,13 @@
 
 #: src/zope/app/utility/browser/__init__.py:89
 msgid "All of the checked utilities were already active"
-msgstr "Alle der ausgewählten Werkzeuge waren schon aktiv"
+msgstr "Alle ausgewählten Werkzeuge waren schon aktiv"
 
 #: src/zope/app/utility/browser/configure.zcml:23
 msgid "A Local Utility Service allows you to register Utilities in this site"
 msgstr ""
-"Ein lokaler Werkzeugdienst erlaubt es Ihnen ein Werkzeug in dieser Seite zu "
-"registrieren."
+"Ein lokaler Werkzeugdienst erlaubt es Ihnen, ein Werkzeug auf diesem "
+"Webplatz zu registrieren."
 
 #: src/zope/app/utility/browser/configure.zcml:23
 msgid "Utility Service"
@@ -5208,7 +5191,7 @@
 
 #: src/zope/app/utility/browser/configure.zcml:62
 msgid "New Utility Registration"
-msgstr "Neue Werkzeug-Registrierung"
+msgstr "Registrierung eines neuen Werkzeugs"
 
 #: src/zope/app/utility/browser/configure.zcml:85
 msgid "Edit Utility Registration"
@@ -5220,7 +5203,7 @@
 
 #: src/zope/app/utility/browser/configureutility.pt:14
 msgid "Utility registrations for interface ${interface}"
-msgstr "Werkzeugregistrierung für Interface ${interface}"
+msgstr "Werkzeugregistrierung für Schnittstelle ${interface}"
 
 #: src/zope/app/utility/browser/configureutility.pt:29
 #: src/zope/app/i18n/browser/synchronize.pt:117
@@ -5228,10 +5211,9 @@
 msgstr "Aktualisieren"
 
 #: src/zope/app/utility/browser/configureutility.pt:9
-msgid ""
-"Utility registrations for interface ${interface} with name ${utility_name}"
+msgid "Utility registrations for interface ${interface} with name ${utility_name}"
 msgstr ""
-"Werkzeugregistrierung für Interface ${interface} mit dem Namen "
+"Werkzeugregistrierung für Schnittstelle ${interface} mit dem Namen "
 "${utility_name}"
 
 #: src/zope/app/utility/browser/utilities.pt:11
@@ -5294,16 +5276,15 @@
 
 #: src/zope/app/utility/interfaces.py:49
 msgid "The interface provided by the utility"
-msgstr "Das Interface das von dem Werkzeug bereitgestellt wird"
+msgstr "Die vom Werkzeug bereitgestellte Schnittstelle"
 
 #: src/zope/app/utility/interfaces.py:57
 msgid "The physical path to the component"
 msgstr "Der physische Pfad zu der Komponente"
 
 #: src/zope/app/utility/vocabulary.py:274
-#, fuzzy
 msgid "(unnamed utility)"
-msgstr "Werkzeug hinzufügen"
+msgstr "(unbenanntes Werkzeug)"
 
 #: src/zope/app/versioncontrol/interfaces.py:197
 msgid "time value indicating the when the bookkeeping information was created"
@@ -5336,8 +5317,7 @@
 msgstr ""
 
 #: src/zope/app/versioncontrol/interfaces.py:226
-msgid ""
-"id of the effective user at the time the bookkeeping information was created"
+msgid "id of the effective user at the time the bookkeeping information was created"
 msgstr ""
 
 #: src/zope/app/versioncontrol/interfaces.py:240
@@ -5370,8 +5350,7 @@
 msgstr "Aktualisiert"
 
 #: src/zope/app/versioncontrol/interfaces.py:254
-msgid ""
-"Message provided by the user at the time of the action.  This may be empty."
+msgid "Message provided by the user at the time of the action.  This may be empty."
 msgstr ""
 
 #: src/zope/app/versioncontrol/interfaces.py:258
@@ -5467,7 +5446,7 @@
 
 #: src/zope/app/workflow/stateful/browser/configure.zcml:121
 msgid "Content Workflows Manager"
-msgstr "Verwalter von Arbeitsabläufen von Inhalten"
+msgstr "Verwalter von Inhalte-Arbeitsabläufen"
 
 #: src/zope/app/workflow/stateful/browser/configure.zcml:121
 msgid "An utility to manage content and workflow interaction."
@@ -5527,7 +5506,8 @@
 "This screen let's you specify which content types (by interface) can receive "
 "which workflows (process definitions)."
 msgstr ""
-"Diese Ansicht erlaubt es ihnen zu sagen, welche Inhaltstypen (per Interface) "
+"Diese Ansicht erlaubt es Ihnen zu sagen, welche Inhaltstypen (per "
+"Schnittstelle) "
 "welche Arbeitsabläufe (Prozessdefinitionen) erhalten könen."
 
 #: src/zope/app/workflow/stateful/browser/contentworkflow_registry.pt:20
@@ -5548,7 +5528,7 @@
 
 #: src/zope/app/workflow/stateful/browser/contentworkflow_registry.pt:67
 msgid "add-mappings-button"
-msgstr "Zuweisung Hinzufügen"
+msgstr "Zuweisung hinzufügen"
 
 #: src/zope/app/workflow/stateful/browser/definition_edit.pt:16
 msgid "Set Workflow-Relevant Data Schema"
@@ -5643,7 +5623,7 @@
 "The condition that is evaluated to decide if the\n"
 "                        transition can be fired or not."
 msgstr ""
-"Die Kondition die evaluiert wird um zu entscheiden ob ein Übergang möglich "
+"Die auszuwertende Bedingung um zu entscheiden, ob ein Übergang möglich "
 "ist oder nicht."
 
 #: src/zope/app/workflow/stateful/interfaces.py:117
@@ -5655,7 +5635,7 @@
 "The script that is evaluated to decide if the\n"
 "                        transition can be fired or not."
 msgstr ""
-"Das Skript das evaluiert wird um zu entscheiden ob ein Übergang möglich ist "
+"Das Skript, das für die Entscheidung evaluiert wird, ob ein Übergang möglich ist "
 "oder nicht."
 
 #: src/zope/app/workflow/stateful/interfaces.py:123
@@ -5719,11 +5699,11 @@
 
 #: src/zope/app/zopetop/widget_macros.pt:63
 msgid "control panels"
-msgstr "Kontrollen"
+msgstr "Steuerungspult"
 
 #: src/zope/app/zopetop/widget_macros.pt:66
 msgid "Control Panels"
-msgstr "Kontrollen"
+msgstr "Steuerungspulte"
 
 #: src/zope/app/zopetop/widget_macros.pt:69
 msgid "system security"
@@ -5779,7 +5759,7 @@
 "Generellen entspricht. Allerdings sind Anwendungs- und Anwendungsserver-"
 "Entwickler nicht das einzige Publikum für Zope 3. Sogenannte \"Skripter\" "
 "sind Inline Code von anderen Technologien wie PHP gewohnt. Inline Code "
-"entspricht daher ihrem denken mehr."
+"entspricht daher ihrem Denken mehr."
 
 #: src/zope/app/zptpage/browser/inlinecode.pt:49
 #: src/zope/app/schema/browser/schema_edit.pt:20
@@ -5796,11 +5776,11 @@
 #: src/zope/app/zptpage/configure.zcml:12
 #: src/zope/app/zptpage/browser/configure.zcml:23
 msgid "A simple, content-based Page Template"
-msgstr "Eine einfache, auf Inhalt basierte Page Template"
+msgstr "Eine einfache, auf Inhalt basierte Seitenschablone"
 
 #: src/zope/app/zptpage/interfaces.py:37
 msgid "The source of the page template."
-msgstr "Der Quellcode der Page Template."
+msgstr "Der Quelltext der Seitenschablone."
 
 #: src/zope/app/zptpage/interfaces.py:41
 msgid "Expand macros"
@@ -5860,7 +5840,7 @@
 
 #: src/zope/schema/_bootstrapinterfaces.py:64
 msgid "Constraint not satisfied"
-msgstr "Beschränkung ist nicht yufriedengestellt"
+msgstr "Einschränkung ist nicht erfüllt"
 
 #: src/zope/schema/_bootstrapinterfaces.py:67
 msgid "Not a container"
@@ -5872,7 +5852,7 @@
 
 #: src/zope/schema/interfaces.py:101
 msgid "A short summary or label"
-msgstr "Eine kurze Zusammenfassung oder Etikett"
+msgstr "Eine kurze Zusammenfassung oder ein Etikett"
 
 #: src/zope/schema/interfaces.py:108
 msgid "A description of the field"
@@ -5905,8 +5885,7 @@
 msgid ""
 "The field default value may be None or a legal\n"
 "                        field value"
-msgstr ""
-"Der \"default\" Wert des Feldes kann None oder ein legaler Feldwert sein"
+msgstr "Der \"default\" Wert des Feldes kann None oder ein legaler Feldwert sein"
 
 #: src/zope/schema/interfaces.py:132
 msgid "Missing Value"
@@ -5934,13 +5913,13 @@
 "        (Fields in separate threads could have the same order.)\n"
 "        "
 msgstr ""
-"Das Ordnungsattribut (order) kann dazu benutzt werden die Reihenfolge der "
-"Felder wie sie im Schema definiert wurden zu bestimmen. Wenn ein Feld nach "
-"einem anderen (im gleichen Thread) erstellt wurde, dann ist seine "
-"Ordnungsnummer größer.\n"
+"        Mit dem Ordnungsattribut (order) kann festgestellt werden, in \n"
+"        welcher Reihenfolge die Felder in einem Schema definiert wurden.\n"
+"       Wenn ein Feld (im gleichen Arbeitsgang) nach einem anderen\n"
+"       erstellt wurde, dann ist seine Ordnungsnummer größer.\n"
 "\n"
-"(Felder in unterschiedlichen Threads könnten die gleiche Ordnungsnummer "
-"haben.)"
+"       (Felder in unterschiedlichen Arbeitsgängen können die gleiche \n"
+"       Ordnungsnummer haben.)"
 
 #: src/zope/schema/interfaces.py:220 src/zope/schema/interfaces.py:303
 msgid "Start of the range"
@@ -5983,46 +5962,45 @@
 
 #: src/zope/schema/interfaces.py:38
 msgid "Wrong contained type"
-msgstr "Falscher enthaltener Wert"
+msgstr "Falscher Typ für Behälterinhalt"
 
 #: src/zope/schema/interfaces.py:384
 msgid "Value Type"
 msgstr "Werttyp"
 
 #: src/zope/schema/interfaces.py:385
-msgid ""
-"Field value items must conform to the given type, expressed via a Field."
-msgstr "Feldwerte müssen sich auf den Typen in diesem Feld anpassen."
+msgid "Field value items must conform to the given type, expressed via a Field."
+msgstr "Feldwerte müssen sich dem Typ dieses Feldes entsprechen."
 
 #: src/zope/schema/interfaces.py:389
 msgid "Unique Members"
-msgstr "Einzigartiges Mitglied"
+msgstr "Eindeutige Mitglieder"
 
 #: src/zope/schema/interfaces.py:390
 msgid "Specifies whether the members of the collection must be unique."
-msgstr "Spezifiziert die Mitglieder der Sammlung die einzigartig sein müssen."
+msgstr "Die Mitglieder der Sammlung müssen eindeutig spezifiziert sein."
 
 #: src/zope/schema/interfaces.py:41
 msgid "One or more entries of sequence are not unique."
-msgstr "Eine oder mehrere Einträge der Sequenz sind nicht einzigartig."
+msgstr "Eine oder mehrere Einträge der Sequenz sind nicht eindeutig."
 
 #: src/zope/schema/interfaces.py:422
 msgid "The Interface that defines the Fields comprising the Object."
-msgstr "Das Interface welches die Felder des Objektes bestimmt."
+msgstr "Die Schnittstelle, die die im Objekt enthaltenen Felder definiert."
 
 #: src/zope/schema/interfaces.py:432
 msgid ""
 "Field keys must conform to the given type, expressed\n"
 "           via a Field.\n"
 "        "
-msgstr "Feldwerte müssen sich auf den Typen in diesem Feld anpassen."
+msgstr "Schlüssel desFeldes müssen mit dem Typ dieses Feldes übereinstimmen."
 
 #: src/zope/schema/interfaces.py:437
 msgid ""
 "Field values must conform to the given type, expressed\n"
 "           via a Field.\n"
 "        "
-msgstr "Feldwerte müssen sich auf den Typen in diesem Feld anpassen."
+msgstr "Feldwerte müssen mit dem Typ dieses Feldes übereinstimmen."
 
 #: src/zope/schema/interfaces.py:44
 msgid "Schema not fully implemented"
@@ -6030,7 +6008,7 @@
 
 #: src/zope/schema/interfaces.py:47
 msgid "Schema not provided"
-msgstr "Schema nicht angegeben"
+msgstr "Schema nicht bereitgestellt."
 
 #: src/zope/schema/interfaces.py:50
 msgid "The specified URI is not valid."
@@ -6038,11 +6016,11 @@
 
 #: src/zope/schema/interfaces.py:53
 msgid "The specified id is not valid."
-msgstr "Die angegebene Id ist nicht gültig."
+msgstr "Die angegebene ID ist nicht gültig."
 
 #: src/zope/schema/interfaces.py:56
 msgid "The specified dotted name is not valid."
-msgstr "Der angegebene punktierte Namen ist nicht gültig."
+msgstr "Der angegebene gepunktete Namen ist nicht gültig."
 
 #: src/zope/schema/interfaces.py:59
 msgid "The field is not bound."
@@ -6066,29 +6044,29 @@
 
 #: src/zope/security/interfaces.py:255
 msgid "The unique identification of the principal."
-msgstr "Die eineindeutige Identifikation des Nutzers."
+msgstr "Die eineindeutige Identifikation des Nutzungsberechtigten."
 
 #: src/zope/security/interfaces.py:261
 msgid "The title of the principal. This is usually used in the UI."
 msgstr ""
-"Der Titel des Prinzipals. Dieser wird normalerweise in der OberflächeI "
-"verwendet."
+"Der Titel des Nutzungsberechtigten. Dieser wird normalerweise in der "
+"Benutzeroberfläche verwendet."
 
 #: src/zope/security/interfaces.py:267
 msgid "A detailed description of the principal."
-msgstr "Eine detailierte Beschreibung des Prinzipals."
+msgstr "Eine detailierte Beschreibung des Nutzungsberechtigten."
 
 #: src/zope/security/interfaces.py:277
 msgid "Groups"
-msgstr ""
+msgstr "Gruppen"
 
 #: src/zope/security/interfaces.py:278
 msgid "List of ids of groups the principal belongs to"
-msgstr ""
+msgstr "Liste der IDs derjenigen Gruppen, zu den der Nutzungsberechtigte gehört."
 
 #: src/zope/security/interfaces.py:288
 msgid "Id as which this permission will be known and used."
-msgstr "ID, unter der diese Erlaubnis bekannt sein und benutzt werden soll."
+msgstr "ID, unter der diese Erlaubnis bekannt sein und benutzt werden wird."
 
 # XXX
 # there is a problem with this message id
@@ -6442,3 +6420,4 @@
 
 #~ msgid "Role(s)"
 #~ msgstr "Rolle(n)"
+

Copied: Zope3/branches/srichter-blow-services/src/zope/app/locking (from rev 29088, Zope3/trunk/src/zope/app/locking)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/mail/delivery.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/mail/delivery.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/mail/delivery.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -22,6 +22,8 @@
 import rfc822
 import threading
 import logging
+import atexit
+import time
 
 from os import unlink, getpid
 from cStringIO import StringIO
@@ -125,7 +127,6 @@
 
     def __init__(self):
         threading.Thread.__init__(self)
-        self.__event = threading.Event()
 
     def setMaildir(self, maildir):
         """Set the maildir.
@@ -167,8 +168,8 @@
         return fromaddr, toaddrs, rest
 
     def run(self, forever=True):
-
-        while True:
+        atexit.register(self.stop)
+        while not self.__stopped:
             for filename in self.maildir:
                 fromaddr = ''
                 toaddrs = ()
@@ -195,9 +196,7 @@
                             filename, exc_info=1)
             else:
                 if forever:
-                    self.__event.wait(3)
-                    if self.__stopped:
-                        return
+                    time.sleep(3)
 
             # A testing plug
             if not forever:
@@ -205,4 +204,3 @@
 
     def stop(self):
         self.__stopped = True
-        self.__event.set()

Modified: Zope3/branches/srichter-blow-services/src/zope/app/mail/metaconfigure.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/mail/metaconfigure.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/mail/metaconfigure.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -53,7 +53,6 @@
         thread = QueueProcessorThread()
         thread.setMailer(mailerObject)
         thread.setQueuePath(queuePath)
-        thread.setDaemon(True)
         thread.start()
 
     _context.action(

Modified: Zope3/branches/srichter-blow-services/src/zope/app/module/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/module/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/module/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -28,7 +28,7 @@
 
   <!-- Enable import of persistent modules -->
   <subscriber
-      factory=".installPersistentModuleImporter"
+      handler=".installPersistentModuleImporter"
       for="zope.app.appsetup.IProcessStartingEvent"
       />
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/observable/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/observable/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/observable/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -7,7 +7,7 @@
       />
 
   <subscriber
-      factory=".observerevent.observerEventNotifier"
+      handler=".observerevent.observerEventNotifier"
       for="zope.app.event.interfaces.IObjectEvent" 
       />
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/pagelet/README.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/pagelet/README.txt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/pagelet/README.txt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -184,16 +184,9 @@
   weight="0"
   />
 
-  >>> name = 'testpagelet'
-  >>> layer = IBrowserRequest
-  >>> slot = IPageletSlot
-  >>> template = u'src/zope/app/pagelet/tests/testfiles/test_pagelet.pt'
-  >>> for_ = Interface
-  >>> permission = 'zope.View'
-  >>> weight = 0
+Setup a test pagelet:
 
-Register the pagelet:
-
+  >>> name = 'testpagelet'
   >>> pagelet_factory = TestPagelet
   >>> defineChecker(pagelet_factory, testChecker)
   >>> gsm.provideAdapter(
@@ -216,10 +209,15 @@
 Setup a view page template called 'index':
 
   >>> from zope.app.pagelet.tests import testfiles
-  >>> index = ViewPageTemplateFile('index_pagelets.pt',
-  ...   'src/zope/app/pagelet/tests/testfiles')
+  >>> import os.path
+  >>> path = os.path.dirname(testfiles.__file__)
+  >>> index = ViewPageTemplateFile('index_pagelets.pt', path)
 
-Call the 'index' (view) on the browser view instance:
+Call the 'index' (view) on the browser view instance the sample pagelet
+'index_pagelets.pt' calls pagelets registred for the slot
+'zope.app.pagelet.interfaces.IPageletSlot'. We registred the 
+'test_pagelet' for this slot in the TestPagelet class. For more info 
+take a look at the index_pagelets.pt' file in the tests/testfiles folder:
 
   >>> html = index(view, request)
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/pluggableauth/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/pluggableauth/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/pluggableauth/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -29,7 +29,7 @@
   <subscriber
         for=".interfaces.IPluggableAuthentication
              zope.app.container.interfaces.IObjectAddedEvent"
-        factory=".PluggableAuthenticationAddSubscriber"
+        handler=".PluggableAuthenticationAddSubscriber"
         />
 
   <content class=".BTreePrincipalSource">

Modified: Zope3/branches/srichter-blow-services/src/zope/app/presentation/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/presentation/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/presentation/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -35,7 +35,6 @@
            zope.app.container.interfaces.IObjectRemovedEvent"
       />
 
-
   <!-- Page Folder -->
 
   <content class=".pagefolder.PageFolder">

Modified: Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -30,7 +30,7 @@
 
   <subscriber
       for="zope.app.appsetup.IDatabaseOpenedEvent"
-      factory=".bootstrap.bootStrapSubscriber"
+      handler=".bootstrap.bootStrapSubscriber"
       />
 
 </configure>

Modified: Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/menu.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/menu.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/menu.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -489,6 +489,113 @@
         _context, action, title, description, icon, filter,
         permission, extra, order)
 
+class MenuItemFactory(object):
+    # XXX this used to be a function created inline within menuItemsDirective,
+    # with the necessary values bound in context.  That approach may be
+    # faster than this one, but it does not encourage approachable doc tests.
+    # Please revise as desired, or remove this triple-X comment if this 
+    # solution is acceptable for now.
+    """generic factory for menu items.
+    
+    The factory needs a class to instantiate.  This will generally implement
+    IBrowserMenuItem.  Here is a dummy example.
+    
+    >>> class DummyBrowserMenuItem(object):
+    ...     "a dummy factory for menu items"
+    ...     def __init__(self, context, request):
+    ...         self.context = context
+    ...         self.request = request
+    ... 
+    
+    To instantiate this class, pass the factory and the other arguments as 
+    described by the signature (and mapped to the IBrowserMenuItem interface).
+    We use dummy values for this example.
+    
+    >>> factory = MenuItemFactory(
+    ...     DummyBrowserMenuItem, 'Title', 'Description', 'Icon', 'Action',
+    ...     'Filter', 'zope.Public', 'Extra', 'Order', 'For_')
+    >>> factory.factory is DummyBrowserMenuItem
+    True
+    
+    The 'zope.Public' permission needs to be translated to CheckerPublic.
+    
+    >>> factory.permission is CheckerPublic
+    True
+    
+    Call the factory with context and request to return the instance.  We 
+    continue to use dummy values.
+    
+    >>> item = factory('Context', 'Request')
+    
+    The returned value should be an instance of the DummyBrowserMenuItem,
+    and have all of the values we initially set on the factory.
+    
+    >>> isinstance(item, DummyBrowserMenuItem)
+    True
+    >>> item.context
+    'Context'
+    >>> item.request
+    'Request'
+    >>> item.title
+    'Title'
+    >>> item.description
+    'Description'
+    >>> item.icon
+    'Icon'
+    >>> item.action
+    'Action'
+    >>> item.filter
+    'Filter'
+    >>> item.permission is CheckerPublic
+    True
+    >>> item.extra
+    'Extra'
+    >>> item.order
+    'Order'
+    >>> item._for
+    'For_'
+    
+    If you pass a permission other than zope.Public to the MenuItemFactory,
+    it should pass through unmodified.
+    
+    >>> factory = MenuItemFactory(
+    ...     DummyBrowserMenuItem, 'Title', 'Description', 'Icon', 'Action',
+    ...     'Filter', 'another.Permission', 'Extra', 'Order', 'For_')
+    >>> factory.permission
+    'another.Permission'
+    """
+    def __init__(self, factory, title, description, icon, action, filter, 
+                 permission, extra, order, for_):
+        self.factory = factory
+        self.title = title
+        self.description = description
+        self.icon = icon
+        self.action = action
+        self.filter = filter
+        if permission == 'zope.Public':
+            permission = CheckerPublic
+        self.permission = permission
+        self.extra = extra
+        self.order = order
+        self.for_ = for_
+    
+    def __call__(self, context, request):
+        item = self.factory(context, request)
+        item.title = self.title
+        item.description = self.description
+        item.icon = self.icon
+        item.action = self.action
+        item.filter = self.filter
+        # we could not set the permission if self.permission is CheckerPublic.
+        # choosing to be explicit for now.
+        item.permission = self.permission
+        item.extra = self.extra
+        item.order = self.order
+        item._for = self.for_
+        if self.permission is not None:
+            checker = InterfaceChecker(IBrowserMenuItem, self.permission)
+            item = proxify(item, checker)
+        return item
 
 class menuItemsDirective(object):
     """Register several menu items for a particular menu.
@@ -525,30 +632,10 @@
             order = _order_counter.get(self.for_, 1)
             _order_counter[self.for_] = order + 1
 
-        def MenuItemFactory(context, request):
-            item = BrowserMenuItem(context, request)
-            item.title = title
-            item.description = description
-            item.icon = icon
-            item.action = action
-            item.filter = filter
-            item.permission = permission
-            item.extra = extra
-            item.order = order
-            item._for = self.for_
-
-            if permission is not None:
-                if permission == 'zope.Public':
-                    perm = CheckerPublic
-                else:
-                    perm = permission
-                checker = InterfaceChecker(IBrowserMenuItem, perm)
-                item = proxify(item, checker)
-
-            return item
-        MenuItemFactory.factory = BrowserMenuItem
-
-        adapter(_context, (MenuItemFactory,), self.menuItemType,
+        factory = MenuItemFactory(
+            BrowserMenuItem, title, description, icon, action, filter, 
+            permission, extra, order, self.for_)
+        adapter(_context, (factory,), self.menuItemType,
                 (self.for_, IBrowserRequest), name=title)
         
     def __call__(self, _context):

Modified: Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/tests/test_addMenuItem.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/tests/test_addMenuItem.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/tests/test_addMenuItem.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -40,7 +40,7 @@
     <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>),
    <InterfaceClass zope.app.publisher.interfaces.browser.AddMenu>,
    'Add an X',
-   <function MenuItemFactory>,
+   <zope.app.publisher.browser.menu.MenuItemFactory object>,
    '')),
  (None,
   <function provideInterface>,
@@ -103,7 +103,7 @@
         <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>),
        <InterfaceClass zope.app.publisher.interfaces.browser.AddMenu>,
        'Add an X',
-       <function MenuItemFactory>,
+       <zope.app.publisher.browser.menu.MenuItemFactory object>,
        '')),
      (None,
       <function provideInterface>,
@@ -137,7 +137,7 @@
         <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>),
        <InterfaceClass zope.app.publisher.interfaces.browser.AddMenu>,
        'Add an X',
-       <function MenuItemFactory>,
+       <zope.app.publisher.browser.menu.MenuItemFactory object>,
        '')),
      (None,
       <function provideInterface>,
@@ -184,7 +184,7 @@
         <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>),
        <InterfaceClass zope.app.publisher.interfaces.browser.AddMenu>,
        'Add an X',
-       <function MenuItemFactory>,
+       <zope.app.publisher.browser.menu.MenuItemFactory object>,
        '')),
      (None,
       <function provideInterface>,

Modified: Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/tests/test_directives.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/tests/test_directives.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/tests/test_directives.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -25,6 +25,7 @@
 from zope.configuration.xmlconfig import xmlconfig, XMLConfig
 from zope.configuration.exceptions import ConfigurationError
 from zope.publisher.browser import TestRequest
+from zope.publisher.interfaces import ILayer
 from zope.publisher.interfaces.browser import IBrowserPublisher
 from zope.publisher.interfaces.browser import IBrowserRequest
 from zope.publisher.interfaces.browser import ISkin, IDefaultSkin
@@ -89,6 +90,17 @@
     def index(self):
         return self
 
+
+class ITestMenu(Interface):
+    """Test menu."""
+
+directlyProvides(ITestMenu, IMenuItemType)
+
+class ITestLayer(ILayer):
+    """Test Layer."""
+
+
+
 class Test(placelesssetup.PlacelessSetup, unittest.TestCase):
 
     def setUp(self):
@@ -874,6 +886,44 @@
         v = zapi.getMultiAdapter((ob, request), name='index.html')
         self.assertEqual(v().strip(), '<html><body><p>test</p></body></html>')
 
+    def test_page_menu_within_different_layers(self):
+        path = os.path.join(tests_path, 'testfiles', 'test.pt')
+        self.assertEqual(
+            zapi.queryMultiAdapter((ob, request), name='index.html'),
+            None)
+
+        xmlconfig(StringIO(template %
+            '''
+            <browser:menu
+                id="test_menu"
+                title="Test menu"
+                interface="zope.app.publisher.browser.tests.test_directives.ITestMenu"/>
+
+            <browser:layer 
+                name="test_layer"
+                interface="zope.app.publisher.browser.tests.test_directives.ITestLayer"
+                />
+
+            <browser:page
+                name="index.html"
+                permission="zope.Public"
+                for="zope.app.component.tests.views.IC"
+                template="%s"
+                menu="test_menu" title="Index"/>
+
+            <browser:page
+                name="index.html"
+                permission="zope.Public"
+                for="zope.app.component.tests.views.IC"
+                menu="test_menu" title="Index"
+                template="%s"
+                layer="zope.app.publisher.browser.tests.test_directives.ITestLayer"/>
+            ''' % (path, path)
+            ))
+
+        v = zapi.getMultiAdapter((ob, request), name='index.html')
+        self.assertEqual(v().strip(), '<html><body><p>test</p></body></html>')
+
     def testtemplateWClass(self):
         path = os.path.join(tests_path, 'testfiles', 'test2.pt')
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/viewmeta.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/viewmeta.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/publisher/browser/viewmeta.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -94,7 +94,7 @@
          attribute='__call__', menu=None, title=None, 
          ):
 
-    _handle_menu(_context, menu, title, [for_], name, permission)
+    _handle_menu(_context, menu, title, [for_], name, permission, layer)
     required = {}
 
     permission = _handle_permission(_context, permission)
@@ -211,7 +211,7 @@
                  menu=None, title=None, provides=Interface,
                  ):
 
-        _handle_menu(_context, menu, title, [for_], name, permission)
+        _handle_menu(_context, menu, title, [for_], name, permission, layer)
 
         permission = _handle_permission(_context, permission)
 
@@ -373,9 +373,12 @@
             callable = provideInterface,
             args = ('', for_)
             )
-        
 
-def _handle_menu(_context, menu, title, for_, name, permission):
+# transient _handle_menu registry
+_registeredMenus = {}
+
+def _handle_menu(_context, menu, title, for_, name, permission, layer=IDefaultBrowserLayer):
+
     if menu or title:
         if not (menu and title):
             raise ConfigurationError(
@@ -385,13 +388,21 @@
                 raise ConfigurationError(
                     "Menus can be specified only for single-view, not for "
                     "multi-views.")
-        return menuItemDirective(
-            _context, menu, for_[0], '@@' + name, title,
-            permission=permission)
 
+        # TODO: menuItemDirective does not handle layers.
+        # IMO this fix is just a work around and menu should 
+        # support layers too.
+        registeredTitles = _registeredMenus.setdefault(menu, {})
+        registered = registeredTitles.setdefault(title, [])
+
+        if for_[0] not in registered:
+            registered.append(for_[0])
+            return menuItemDirective(
+                _context, menu, for_[0], '@@' + name, title,
+                permission=permission)
+
     return []
 
-
 def _handle_permission(_context, permission):
     if permission == 'zope.Public':
         permission = CheckerPublic

Modified: Zope3/branches/srichter-blow-services/src/zope/app/publisher/xmlrpc/README.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/publisher/xmlrpc/README.txt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/publisher/xmlrpc/README.txt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -4,7 +4,7 @@
 XML-RPC Methods
 ---------------
 
-There are two ways to write XML-RPV views. You can write views that
+There are two ways to write XML-RPC views. You can write views that
 provide "methods" for other objects, and you can write views that have
 their own methods.  Let's look at the former case first, since it's a
 little bit simpler.
@@ -39,7 +39,7 @@
 Now, we'll add some items to the root folder:
 
   >>> print http(r"""
-  ... POST /++skin++Debug/@@contents.html HTTP/1.1
+  ... POST /@@contents.html HTTP/1.1
   ... Authorization: Basic bWdyOm1ncnB3
   ... Content-Length: 73
   ... Content-Type: application/x-www-form-urlencoded
@@ -121,7 +121,7 @@
   </methodResponse>
   <BLANKLINE>
 
-Named XM-RPC Views
+Named XML-RPC Views
 ------------------
 
 Now let's look at views that have their own methods or other
@@ -131,7 +131,7 @@
    .../somefolder/listing/contents
 
 To make this possible, the view has to support traversal, so that,
-when it is traversed, it traverses to it's attributes.  To supplot
+when it is traversed, it traverses to its attributes.  To support
 traversal, you can implement or provide an adapter to
 `zope.publisher.interfaces.IPublishTraverse`. It's actually better to
 provide an adapter so that accesses to attributes during traversal are

Modified: Zope3/branches/srichter-blow-services/src/zope/app/registration/registration.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/registration/registration.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/registration/registration.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -18,6 +18,7 @@
 from zope.deprecation import deprecated
 
 from zope.app.component import registration
+from zope.component import subscribers
 
 RegistrationEvent = registration.RegistrationEvent
 RegistrationActivatedEvent = registration.RegistrationActivatedEvent

Modified: Zope3/branches/srichter-blow-services/src/zope/app/rotterdam/template.pt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/rotterdam/template.pt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/rotterdam/template.pt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -51,14 +51,7 @@
         </metal:block>
         <metal:block define-slot="login_logout">
           <metal:macro define-macro="login_logout">
-          <a href=""
-            tal:attributes="href string:@@logout.html?nextURL=${request/URL/url:quote}"
-            tal:condition="python: hasattr(request.principal, 'getLogin')"
-            i18n:translate="">[Logout]</a>
-          <a href=""
-            tal:attributes="href string:@@login.html?nextURL=${request/URL/url:quote}"
-            tal:condition="python: not hasattr(request.principal, 'getLogin')"
-            i18n:translate="">[Login]</a>
+          <tal:block content="structure context/@@login_logout" />
           </metal:macro>
         </metal:block>
       </div>

Modified: Zope3/branches/srichter-blow-services/src/zope/app/schema/metadirectives.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/schema/metadirectives.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/schema/metadirectives.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -38,11 +38,10 @@
 
     name = TextLine(
         title=u"Name",
-        description=u'Provides a title for the source type.", The name of the '\
+        description=u'Provides a title for the source type. The name of the ' \
                     u'vocabulary; this can be used as the value for the ' \
-                    u'"vocabulary" argument to the VocabularyField and ' \
-                    u'VocabularyMultiField constructors to cause this ' \
-                    u'vocabulary to be used.',
+                    u'"vocabulary" argument to the Choice field ' \
+                    u'constructor to cause this vocabulary to be used.',
         required=True)
 
     factory = GlobalObject(

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/browser/auth.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/browser/auth.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/browser/auth.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -15,11 +15,12 @@
 
 $Id$
 """
+import urllib
 from zope.interface import implements
 from zope.i18n import translate
 from zope.app.publisher.interfaces.http import ILogin, ILogout
 from zope.app.security.interfaces import IAuthentication
-from zope.app.security.principalregistry import UnauthenticatedPrincipal
+from zope.app.security.interfaces import IUnauthenticatedPrincipal
 from zope.app.pagetemplate import ViewPageTemplateFile
 from zope.proxy import removeAllProxies
 from zope.app.i18n import ZopeMessageIDFactory as _
@@ -35,7 +36,12 @@
         self.request = request
 
     def render(self, name):
+        sourcename = 'principals.zcml'
         html = []
+
+        # add sub title for source search field
+        html.append('<h4 i18n:translate="">%s</h4>' % sourcename)
+        # start row for search fields
         html.append('<div class="row">')
         html.append('<div class="label">')
         html.append('Search String')
@@ -45,10 +51,17 @@
         html.append('</div>')
         html.append('</div>')
 
-        html.append('<br /><input type="submit" name="%s" value="%s" />'
+        # add search button for search fields
+        html.append('<div class="row">')
+        html.append('<div class="field">')
+        html.append('<input type="submit" name="%s" value="%s" />'
                     % (name+'.search',
                        translate(search_label, context=self.request)))
+        html.append('</div>')
 
+        # end row
+        html.append('</div>')
+
         return '\n'.join(html)
 
     def results(self, name):
@@ -64,8 +77,7 @@
 
     def login(self, nextURL=None):
         """See zope.app.security.interfaces.ILogin"""
-        if isinstance(removeAllProxies(self.request.principal), \
-                      UnauthenticatedPrincipal):
+        if IUnauthenticatedPrincipal.providedBy(self.request.principal):
             self.request.unauthorized("basic realm='Zope'")
             return self.failed()
         else:
@@ -91,7 +103,7 @@
 
     def logout(self, nextURL=None):
         """See zope.app.security.interfaces.ILogout"""
-        if not isinstance(self.request.principal, UnauthenticatedPrincipal):
+        if not IUnauthenticatedPrincipal.providedBy(self.request.principal):
             self.request.unauthorized("basic realm='Zope'")
             if nextURL:
                 return self.redirect()
@@ -106,3 +118,18 @@
     redirect = ViewPageTemplateFile('redirect.pt')
 
 
+class LoginLogout:
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    def __call__(self):
+        if IUnauthenticatedPrincipal.providedBy(self.request.principal):
+            page = '@@login.html'
+            label = _('[Login]')
+        else:
+            page = '@@logout.html'
+            label = _('[Logout]')
+        return '<a href="%s?nextURL=%s">%s</a>' % (
+            page, urllib.quote(self.request.getURL()), label)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/browser/authutilitysearchview.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/browser/authutilitysearchview.txt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/browser/authutilitysearchview.txt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -28,6 +28,7 @@
 This allows us to render a search form.
 
   >>> print view.render('test') # doctest: +NORMALIZE_WHITESPACE
+  <h4 i18n:translate="">principals.zcml</h4>
   <div class="row">
   <div class="label">
   Search String
@@ -36,7 +37,11 @@
   <input type="text" name="test.searchstring" />
   </div>
   </div>
-  <br /><input type="submit" name="test.search" value="Search" />
+  <div class="row">
+  <div class="field">
+  <input type="submit" name="test.search" value="Search" />
+  </div>
+  </div>
 
 If we ask for results:
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/browser/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/browser/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/browser/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -7,14 +7,14 @@
       for="zope.app.security.interfaces.IAuthentication
            zope.publisher.interfaces.browser.IBrowserRequest"
       provides="zope.app.form.browser.interfaces.ISourceQueryView"
-      factory="zope.app.security.browser.auth.AuthUtilitySearchView" 
+      factory="zope.app.security.browser.auth.AuthUtilitySearchView"
       />
 
   <adapter
       for="zope.app.security.interfaces.IPrincipalSource
            zope.publisher.interfaces.browser.IBrowserRequest"
       provides="zope.app.form.browser.interfaces.ITerms"
-      factory="zope.app.security.browser.principalterms.PrincipalTerms" 
+      factory="zope.app.security.browser.principalterms.PrincipalTerms"
       />
 
   <browser:tool
@@ -42,6 +42,13 @@
       allowed_interface="zope.app.publisher.interfaces.http.ILogout"
       />
 
+  <browser:page
+      name="login_logout"
+      for="*"
+      class=".auth.LoginLogout"
+      permission="zope.Public"
+      />
+
   <browser:tool
       interface="..interfaces.IPermission"
       title="Permission"

Copied: Zope3/branches/srichter-blow-services/src/zope/app/security/browser/loginlogout.txt (from rev 29088, Zope3/trunk/src/zope/app/security/browser/loginlogout.txt)


Property changes on: Zope3/branches/srichter-blow-services/src/zope/app/security/browser/loginlogout.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/browser/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/browser/tests.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/browser/tests.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -28,6 +28,9 @@
         doctest.DocFileSuite('principalterms.txt',
                              setUp=placelesssetup.setUp,
                              tearDown=placelesssetup.tearDown),
+        doctest.DocFileSuite('loginlogout.txt',
+                             setUp=placelesssetup.setUp,
+                             tearDown=placelesssetup.tearDown),
         ))
 
 if __name__ == '__main__':

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -10,7 +10,7 @@
                    Public resources are always accessible."
       />
 
-  <vocabulary 
+  <vocabulary
       name="Permissions"
       factory="zope.app.component.vocabulary.UtilityVocabulary"
       interface="zope.security.interfaces.IPermission" />
@@ -23,15 +23,15 @@
   <include file="_protections.zcml" />
 
   <utility
-      provides=".interfaces.IAuthentication" 
+      provides=".interfaces.IAuthentication"
       component=".principalregistry.principalRegistry" />
 
   <localUtility class=".permission.LocalPermission">
     <factory
         id="zope.app.security.Permission"
         />
-    <allow 
-        interface=".interfaces.IPermission" 
+    <allow
+        interface=".interfaces.IPermission"
         />
     <require
         permission="zope.Security"
@@ -40,13 +40,15 @@
   </localUtility>
 
   <subscriber
-     for="..component.interfaces.registration.IRegistrationActivatedEvent"
-     factory=".permission.setIdOnActivation"
+     for="zope.security.interfaces.IPermission
+          ..component.interfaces.registration.IRegistrationActivatedEvent"
+     handler=".permission.setIdOnActivation"
      />
 
   <subscriber
-     for="..component.interfaces.registration.IRegistrationDeactivatedEvent"
-     factory=".permission.unsetIdOnDeactivation"
+     for="zope.security.interfaces.IPermission
+          ..component.interfaces.registration.IRegistrationDeactivatedEvent"
+     handler=".permission.unsetIdOnDeactivation"
      />
 
   <content class=".permission.Permission">
@@ -80,9 +82,9 @@
       title="[manage-content-permission] Manage Content"
       />
 
-  <permission 
-      id="zope.ManageBindings" 
-      title="[manage-service-bindings-permission] Manage Service Bindings" 
+  <permission
+      id="zope.ManageBindings"
+      title="[manage-service-bindings-permission] Manage Service Bindings"
       />
 
   <permission
@@ -91,9 +93,9 @@
       description="Manage executable code, including Python, SQL, ZPT, etc."
       />
 
-  <permission 
-      id="zope.ManageServices" 
-      title="[manage-services-permission] Manage Services" 
+  <permission
+      id="zope.ManageServices"
+      title="[manage-services-permission] Manage Services"
       />
 
   <permission 
@@ -116,7 +118,7 @@
   <adapter
       factory=".basicauthadapter.BasicAuthAdapter"
       provides=".interfaces.ILoginPassword"
-      for="zope.publisher.interfaces.http.IHTTPCredentials" 
+      for="zope.publisher.interfaces.http.IHTTPCredentials"
       />
 
   <adapter

Copied: Zope3/branches/srichter-blow-services/src/zope/app/security/globalprincipals.txt (from rev 29088, Zope3/trunk/src/zope/app/security/globalprincipals.txt)


Property changes on: Zope3/branches/srichter-blow-services/src/zope/app/security/globalprincipals.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/interfaces.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/interfaces.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/interfaces.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -18,7 +18,7 @@
 from zope.interface import Interface
 from zope.app.i18n import ZopeMessageIDFactory as _
 from zope.schema import Text, TextLine
-from zope.security.interfaces import IPrincipal, IPermission
+from zope.security.interfaces import IPrincipal, IPermission, IGroup
 from zope.schema.interfaces import ISource
 
 from zope.exceptions import NotFoundError
@@ -33,6 +33,24 @@
     Authenticated principals are preferable to UnauthenticatedPrincipals.
     """
 
+class IUnauthenticatedGroup(IGroup):
+    """A group containing unauthenticated users
+    """
+
+class IAuthenticatedGroup(IGroup):
+    """A group containing authenticated users
+    """
+
+class IEveryoneGroup(IGroup):
+    """A group containing all users
+    """
+
+class IUnauthenticatedPrincipal(IPrincipal):
+    """A principal that hasn't been authenticated.
+
+    Authenticated principals are preferable to UnauthenticatedPrincipals.
+    """
+
 class IAuthentication(Interface):
     """Provide support for establishing principals for requests.
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/meta.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/meta.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/meta.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -15,11 +15,29 @@
       handler=".metaconfigure.principal" />
 
   <meta:directive 
+      name="unauthenticatedPrincipal" 
       namespace="http://namespaces.zope.org/zope"
-      name="unauthenticatedPrincipal" 
       schema=".metadirectives.IDefineUnauthenticatedPrincipalDirective"
       handler=".metaconfigure.unauthenticatedPrincipal" />
 
+  <meta:directive 
+      name="unauthenticatedGroup" 
+      namespace="http://namespaces.zope.org/zope"
+      schema=".metadirectives.IDefineUnauthenticatedGroupDirective"
+      handler=".metaconfigure.unauthenticatedGroup" />
+
+  <meta:directive 
+      name="authenticatedGroup" 
+      namespace="http://namespaces.zope.org/zope"
+      schema=".metadirectives.IDefineAuthenticatedGroupDirective"
+      handler=".metaconfigure.authenticatedGroup" />
+
+  <meta:directive 
+      name="everybodyGroup" 
+      namespace="http://namespaces.zope.org/zope"
+      schema=".metadirectives.IDefineEverybodyGroupDirective"
+      handler=".metaconfigure.everybodyGroup" />
+
   <meta:directive
       name="securityPolicy"
       namespace="http://namespaces.zope.org/zope"

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/metaconfigure.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/metaconfigure.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/metaconfigure.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -15,16 +15,19 @@
 
 $Id$
 """
-from zope.app.component.metaconfigure import utility
 
+from zope import component
 from zope.security.checker import moduleChecker, Checker, defineChecker
 from zope.security.checker import CheckerPublic
 from zope.security.management import setSecurityPolicy
-from zope.app.security.interfaces import IPermission
+from zope.security.interfaces import IPermission
+
+from zope.app.component.metaconfigure import utility
+
 from zope.app.security.permission import Permission
-from zope.app.security.principalregistry import principalRegistry
+from zope.app.security import principalregistry
+from zope.app.security import interfaces
 
-
 def securityPolicy(_context, component):
 
     _context.action(
@@ -93,19 +96,112 @@
     utility(_context, IPermission, permission, name=id)
 
 
+def _principal():
+    group = component.queryUtility(interfaces.IAuthenticatedGroup)
+    if group is not None:
+        _authenticatedGroup(group.id)
+    group = component.queryUtility(interfaces.IEveryoneGroup)
+    if group is not None:
+        _everybodyGroup(group.id)
+
 def principal(_context, id, title, login, password, description=''):
     _context.action(
         discriminator = ('principal', id),
-        callable = principalRegistry.definePrincipal,
+        callable = principalregistry.principalRegistry.definePrincipal,
         args = (id, title, description, login, password) )
+    _context.action(discriminator = None, callable = _principal, args = ())
 
 
+def _unauthenticatedPrincipal():
+    group = component.queryUtility(interfaces.IUnauthenticatedGroup)
+    if group is not None:
+        _unauthenticatedGroup(group.id)
+    group = component.queryUtility(interfaces.IEveryoneGroup)
+    if group is not None:
+        _everybodyGroup(group.id)
+
 def unauthenticatedPrincipal(_context, id, title, description=''):
+    principal = principalregistry.UnauthenticatedPrincipal(
+        id, title, description)
     _context.action(
         discriminator = 'unauthenticatedPrincipal',
-        callable = principalRegistry.defineDefaultPrincipal,
-        args = (id, title, description) )
+        callable = principalregistry.principalRegistry.defineDefaultPrincipal,
+        args = (id, title, description, principal) )
+    utility(_context, interfaces.IUnauthenticatedPrincipal, principal)
+    _context.action(
+        discriminator = None,
+        callable = _unauthenticatedPrincipal,
+        args = (),
+        )
 
+def _unauthenticatedGroup(group):
+    p = principalregistry.principalRegistry.unauthenticatedPrincipal()
+    if p is not None:
+        p.groups.append(group)
+
+def unauthenticatedGroup(_context, id, title, description=''):
+    principal = principalregistry.UnauthenticatedGroup(
+        id, title, description)
+    utility(_context, interfaces.IUnauthenticatedGroup, principal)
+    _context.action(
+        discriminator = None,
+        callable = _unauthenticatedGroup,
+        args = (principal.id, ),
+        )
+    _context.action(
+        discriminator = None,
+        callable = principalregistry.principalRegistry.registerGroup,
+        args = (principal, ),
+        )
+
+def _authenticatedGroup(group):
+    for p in principalregistry.principalRegistry.getPrincipals(''):
+        if not isinstance(p, principalregistry.Principal):
+            continue
+        if group not in p.groups:
+            p.groups.append(group)
+
+def authenticatedGroup(_context, id, title, description=''):
+    principal = principalregistry.AuthenticatedGroup(
+        id, title, description)
+    utility(_context, interfaces.IAuthenticatedGroup, principal)
+    _context.action(
+        discriminator = None,
+        callable = _authenticatedGroup,
+        args = (principal.id, ),
+        )
+    _context.action(
+        discriminator = None,
+        callable = principalregistry.principalRegistry.registerGroup,
+        args = (principal, ),
+        )
+
+def _everybodyGroup(group):
+    for p in principalregistry.principalRegistry.getPrincipals(''):
+        if not isinstance(p, principalregistry.Principal):
+            continue
+        if group not in p.groups:
+            p.groups.append(group)
+    p = principalregistry.principalRegistry.unauthenticatedPrincipal()
+    if p is not None:
+        p.groups.append(group)
+
+def everybodyGroup(_context, id, title, description=''):
+    principal = principalregistry.EverybodyGroup(
+        id, title, description)
+    utility(_context, interfaces.IEveryoneGroup, principal)
+    _context.action(
+        discriminator = None,
+        callable = _everybodyGroup,
+        args = (principal.id, ),
+        )
+    _context.action(
+        discriminator = None,
+        callable = principalregistry.principalRegistry.registerGroup,
+        args = (principal, ),
+        )
+
+
 def redefinePermission(_context, from_, to):
     _context = _context.context
     

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/metadirectives.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/metadirectives.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/metadirectives.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -131,6 +131,15 @@
 class IDefineUnauthenticatedPrincipalDirective(IBasePrincipalDirective):
     """Define a new unauthenticated principal."""
 
+class IDefineUnauthenticatedGroupDirective(IBasePrincipalDirective):
+    """Define the unauthenticated group."""
+
+class IDefineAuthenticatedGroupDirective(IBasePrincipalDirective):
+    """Define the authenticated group."""
+
+class IDefineEverybodyGroupDirective(IBasePrincipalDirective):
+    """Define the everybody group."""
+
 class IRedefinePermission(Interface):
     """Define a permission to replace another permission."""
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/permission.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/permission.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/permission.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -44,7 +44,7 @@
         self.description = description
 
 
-def setIdOnActivation(event):
+def setIdOnActivation(permission, event):
     """Set the permission id upon registration activation.
 
     Let's see how this notifier can be used. First we need to create an event
@@ -66,28 +66,14 @@
     Now we pass the event into this function, and the id of the permission
     should be set to 'perm1'.
 
-    >>> setIdOnActivation(event)
+    >>> setIdOnActivation(perm1, event)
     >>> perm1.id
     'perm1'
-
-    If the function is called and the component is not a local permission,
-    nothing is done:
-
-    >>> class Foo:
-    ...     id = 'no id'
-    >>> foo = Foo()
-    >>> event = registration.RegistrationActivatedEvent(
-    ...     Registration(foo, 'foo'))
-    >>> setIdOnActivation(event)
-    >>> foo.id
-    'no id'
     """
-    perm = event.object.component
-    if isinstance(perm, LocalPermission):
-        perm.id = event.object.name
+    permission.id = event.object.name
 
 
-def unsetIdOnDeactivation(event):
+def unsetIdOnDeactivation(permission, event):
     """Unset the permission id up registration deactivation.
 
     Let's see how this notifier can be used. First we need to create an event
@@ -108,25 +94,11 @@
     Now we pass the event into this function, and the id of the permission
     should be set to NULL_ID.
 
-    >>> unsetIdOnDeactivation(event)
+    >>> unsetIdOnDeactivation(perm1, event)
     >>> perm1.id
     u'<permission not activated>'
-
-    If the function is called and the component is not a local permission,
-    nothing is done:
-
-    >>> class Foo:
-    ...     id = 'foo'
-    >>> foo = Foo()
-    >>> event = registration.RegistrationDeactivatedEvent(
-    ...     Registration(foo, 'foo'))
-    >>> unsetIdOnDeactivation(event)
-    >>> foo.id
-    'foo'
     """
-    perm = event.object.component
-    if isinstance(perm, LocalPermission):
-        perm.id = NULL_ID
+    permission.id = NULL_ID
 
 
 def checkPermission(context, permission_id):

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/principalregistry.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/principalregistry.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/principalregistry.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -19,9 +19,8 @@
 from zope.interface import implements
 from zope.app.security.interfaces import PrincipalLookupError
 from zope.app import zapi
-from zope.app.security.interfaces import ILoginPassword
-from zope.app.security.interfaces import IAuthentication, IPrincipal
-from zope.app.security.interfaces import IUnauthenticatedPrincipal
+from zope.security.interfaces import IPrincipal, IGroupAwarePrincipal
+from zope.app.security import interfaces
 from zope.app.container.contained import Contained, contained
 from warnings import warn
 
@@ -30,12 +29,12 @@
 
 class PrincipalRegistry(object):
 
-    implements(IAuthentication)
+    implements(interfaces.IAuthentication)
 
     # Methods implementing IAuthentication
 
     def authenticate(self, request):
-        a = ILoginPassword(request, None)
+        a = interfaces.ILoginPassword(request, None)
         if a is not None:
             login = a.getLogin()
             if login is not None:
@@ -49,21 +48,22 @@
     __defaultid = None
     __defaultObject = None
 
-    def defineDefaultPrincipal(self, principal, title, description=''):
-        id = principal
+    def defineDefaultPrincipal(self, id, title, description='',
+                               principal=None):
         if id in self.__principalsById:
             raise DuplicateId(id)
         self.__defaultid = id
-        p = UnauthenticatedPrincipal(principal, title, description)
-        self.__defaultObject = contained(p, self, id)
-        return p
+        if principal is None:
+            principal = UnauthenticatedPrincipal(id, title, description)
+        self.__defaultObject = contained(principal, self, id)
+        return principal
 
     def unauthenticatedPrincipal(self):
         return self.__defaultObject
 
     def unauthorized(self, id, request):
         if id is None or id is self.__defaultid:
-            a = ILoginPassword(request)
+            a = interfaces.ILoginPassword(request)
             a.needLogin(realm="zope")
 
     def getPrincipal(self, id):
@@ -106,6 +106,13 @@
 
         return p
 
+    def registerGroup(self, group):
+        id = group.id
+        if id in self.__principalsById or id == self.__defaultid:
+            raise DuplicateId(id)
+
+        self.__principalsById[group.id] = group
+
     def _clear(self):
         self.__init__()
 
@@ -122,11 +129,16 @@
         self.id = id
         self.title = title
         self.description = description
+        self.groups = []
 
+class Group(PrincipalBase):
 
+    def getLogin(self):
+        return '' # to make registry search happy
+
 class Principal(PrincipalBase):
 
-    implements(IPrincipal)
+    implements(IGroupAwarePrincipal)
 
     def __init__(self, id, title, description, login, pw):
         super(Principal, self).__init__(id, title, description)
@@ -142,4 +154,17 @@
 
 class UnauthenticatedPrincipal(PrincipalBase):
 
-    implements(IUnauthenticatedPrincipal)
+    implements(interfaces.IUnauthenticatedPrincipal)
+
+class UnauthenticatedGroup(Group):
+
+    implements(interfaces.IUnauthenticatedGroup)
+
+class AuthenticatedGroup(Group):
+
+    implements(interfaces.IAuthenticatedGroup)
+
+class EverybodyGroup(Group):
+
+    implements(interfaces.IEveryoneGroup)
+    

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/tests/test_directives.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/tests/test_directives.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/tests/test_directives.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -18,8 +18,10 @@
 import unittest
 from pprint import PrettyPrinter
 from zope.interface import Interface, Attribute
-from zope.testing.doctestunit import DocTestSuite
+from zope.testing import doctest
+from zope.configuration import xmlconfig
 
+import zope.app.security
 from zope.security.checker import moduleChecker
 from zope.app.testing import ztapi
 from zope.app.testing.placelesssetup import setUp, tearDown, PlacelessSetup
@@ -216,10 +218,23 @@
     def testRedefinePermission(self):
         self.assertEqual(perms, ['zope.Security'])
 
+def zcml(s):
+    context = xmlconfig.file('meta.zcml', package=zope.app.security)
+    xmlconfig.string(s, context)
+
+def reset():
+    tearDown()
+    setUp()
+
 def test_suite():
     return unittest.TestSuite((
-        DocTestSuite(setUp=setUp, tearDown=tearDown),
+        doctest.DocTestSuite(setUp=setUp, tearDown=tearDown),
         unittest.makeSuite(DirectivesTest),
+        doctest.DocFileSuite(
+            '../globalprincipals.txt',
+            globs={'zcml': zcml, 'reset': reset},
+            setUp=setUp, tearDown=tearDown,
+            )
         ))
 
 if __name__ == '__main__': unittest.main()

Modified: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/browser/manage_access.pt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/browser/manage_access.pt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/browser/manage_access.pt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -17,7 +17,7 @@
       tal:condition="status"
       tal:content="status" />
 
-  <form action="AllRolePermissions.html" method="post">
+  <form action="AllRolePermissions.html" method="POST">
 
     <table width="100%" cellspacing="0" cellpadding="2" border="0" 
            nowrap="nowrap">

Modified: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/browser/manage_roleform.pt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/browser/manage_roleform.pt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/browser/manage_roleform.pt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -22,7 +22,7 @@
     </p>
 
 
-    <form action="AllRolePermissions.html" method="get">
+    <form action="AllRolePermissions.html" method="POST">
       <input type="hidden" name="role_id" value="Role ID"
              tal:attributes="value role/id" />
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -69,13 +69,15 @@
   </localUtility>
 
   <subscriber
-     for="..component.interfaces.registration.IRegistrationActivatedEvent"
-     factory=".role.setIdOnActivation"
+     for=".interfaces.IRole
+         ..component.interfaces.registration.IRegistrationActivatedEvent"
+     handler=".role.setIdOnActivation"
      />
 
   <subscriber
-     for="..component.interfaces.registration.IRegistrationDeactivatedEvent"
-     factory=".role.unsetIdOnDeactivation"
+     for=".interfaces.IRole
+          ..component.interfaces.registration.IRegistrationDeactivatedEvent"
+     handler=".role.unsetIdOnDeactivation"
      />
 
   <!-- Include browser package -->

Modified: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/role.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/role.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/role.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -47,7 +47,7 @@
 from zope.app.component.site import UtilityRegistration
 RoleRegistration = UtilityRegistration
 
-def setIdOnActivation(event):
+def setIdOnActivation(role, event):
     """Set the permission id upon registration activation.
 
     Let's see how this notifier can be used. First we need to create an event
@@ -68,28 +68,14 @@
     Now we pass the event into this function, and the id of the role should be
     set to 'role1'.
 
-    >>> setIdOnActivation(event)
+    >>> setIdOnActivation(role1, event)
     >>> role1.id
     'role1'
-
-    If the function is called and the component is not a local permission,
-    nothing is done:
-
-    >>> class Foo:
-    ...     id = 'no id'
-    >>> foo = Foo()
-    >>> event = registration.RegistrationActivatedEvent(
-    ...     Registration(foo, 'foo'))
-    >>> setIdOnActivation(event)
-    >>> foo.id
-    'no id'
     """
-    role = event.object.component
-    if isinstance(role, LocalRole):
-        role.id = event.object.name
+    role.id = event.object.name
 
 
-def unsetIdOnDeactivation(event):
+def unsetIdOnDeactivation(role, event):
     """Unset the permission id up registration deactivation.
 
     Let's see how this notifier can be used. First we need to create an event
@@ -110,28 +96,14 @@
     Now we pass the event into this function, and the id of the role should be
     set to NULL_ID.
 
-    >>> unsetIdOnDeactivation(event)
+    >>> unsetIdOnDeactivation(role1, event)
     >>> role1.id
     u'<role not activated>'
-
-    If the function is called and the component is not a local role,
-    nothing is done:
-
-    >>> class Foo:
-    ...     id = 'foo'
-    >>> foo = Foo()
-    >>> event = registration.RegistrationDeactivatedEvent(
-    ...     Registration(foo, 'foo'))
-    >>> unsetIdOnDeactivation(event)
-    >>> foo.id
-    'foo'
     """
-    role = event.object.component
-    if isinstance(role, LocalRole):
-        role.id = NULL_ID
+    role.id = NULL_ID
 
-    
 
+
 def checkRole(context, role_id):
     names = [name for name, util in zapi.getUtilitiesFor(IRole, context)]
     if not role_id in names:

Copied: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/functional.py (from rev 29088, Zope3/trunk/src/zope/app/securitypolicy/tests/functional.py)
===================================================================
--- Zope3/trunk/src/zope/app/securitypolicy/tests/functional.py	2005-02-09 01:00:34 UTC (rev 29088)
+++ Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/functional.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -0,0 +1,37 @@
+##############################################################################
+#
+# Copyright (c) 2004 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.
+#
+##############################################################################
+"""Functional test case support
+
+$Id$
+"""
+from zope import interface
+from zope.app.testing import functional
+
+class ManagerSetup:
+    interface.implements(functional.IManagerSetup)
+
+    def setUpManager(self):
+        functional.HTTPCaller()(grant_request, handle_errors=False)
+
+grant_request = (r"""
+POST /@@grant.html HTTP/1.1
+Authorization: Basic Z2xvYmFsbWdyOmdsb2JhbG1ncnB3
+Content-Length: 5796
+Content-Type: application/x-www-form-urlencoded
+
+field.principal=em9wZS5tZ3I_"""
+"""&field.principal.displayed=y"""
+"""&GRANT_SUBMIT=Change"""
+"""&field.em9wZS5tZ3I_.role.zope.Manager=allow"""
+"""&field.em9wZS5tZ3I_.role.zope.Manager-empty-marker=1""")


Property changes on: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/functional.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Copied: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/functional.zcml (from rev 29088, Zope3/trunk/src/zope/app/securitypolicy/tests/functional.zcml)


Property changes on: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/functional.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/zopepolicy.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/zopepolicy.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/zopepolicy.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -26,6 +26,7 @@
 
 from zope.app import zapi
 
+from zope.app.security.interfaces import PrincipalLookupError
 from zope.app.security.settings import Allow, Deny, Unset
 
 from zope.app.securitypolicy.principalpermission \

Modified: Zope3/branches/srichter-blow-services/src/zope/app/server/mkzopeinstance.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/server/mkzopeinstance.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/server/mkzopeinstance.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -37,13 +37,12 @@
     if argv is None:
         argv = sys.argv
     try:
-        options = parse_args(argv)
+        options = parse_args(argv, from_checkout)
     except SystemExit, e:
         if e.code:
             return 2
         else:
             return 0
-    options.from_checkout = from_checkout
     app = Application(options)
     try:
         return app.process()
@@ -106,7 +105,7 @@
 
         # now create the instance!
         self.copy_skeleton()
-        if options.from_checkout:
+        if options.add_package_includes:
             # need to copy ZCML differently since it's not in the skeleton:
             import __main__
             swhome = os.path.dirname(
@@ -231,12 +230,9 @@
 """
 
 
-def parse_args(argv):
+def parse_args(argv, from_checkout=False):
     """Parse the command line, returning an object representing the input."""
     path, prog = os.path.split(os.path.realpath(argv[0]))
-    basedir = os.path.dirname(path)
-    # no assurance that this exists!
-    default_skeleton = os.path.join(basedir, "zopeskel")
     version = "%prog for " + zopeversion.ZopeVersionUtility.getZopeVersion()
     p = optparse.OptionParser(prog=prog,
                               usage="%prog [options]",
@@ -244,12 +240,17 @@
     p.add_option("-d", "--dir", dest="destination", metavar="DIR",
                  help="the dir in which the instance home should be created")
     p.add_option("-s", "--skelsrc", dest="skeleton", metavar="DIR",
-                 default=default_skeleton,
                  help="template skeleton directory")
     p.add_option("-u", "--user", dest="username", metavar="USER:PASSWORD",
                  help="set the user name and password of the initial user")
     options, args = p.parse_args(argv[1:])
-    options.from_checkout = False
+    if options.skeleton is None:
+        options.add_package_includes = from_checkout
+        basedir = os.path.dirname(path)
+        # no assurance that this exists!
+        options.skeleton = os.path.join(basedir, "zopeskel")
+    else:
+        options.add_package_includes = False
     options.program = prog
     options.version = version
     if args:

Modified: Zope3/branches/srichter-blow-services/src/zope/app/server/tests/test_mkzopeinstance.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/server/tests/test_mkzopeinstance.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/server/tests/test_mkzopeinstance.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -96,10 +96,12 @@
     def test_with_skeleton_long(self):
         options = self.parse_args(["--skelsrc", "some/dir"])
         self.assertEqual(options.skeleton, "some/dir")
+        self.failIf(options.add_package_includes)
 
     def test_with_skeleton_short(self):
         options = self.parse_args(["-s", "some/dir"])
         self.assertEqual(options.skeleton, "some/dir")
+        self.failIf(options.add_package_includes)
 
     def test_without_username(self):
         options = self.parse_args([])
@@ -280,7 +282,7 @@
     destination = None
     version = "[test-version]"
     program = "[test-program]"
-    from_checkout = False
+    add_package_includes = False
 
 
 def test_suite():

Modified: Zope3/branches/srichter-blow-services/src/zope/app/session/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/session/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/session/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -66,7 +66,7 @@
 
   <subscriber
       for="zope.app.appsetup.IDatabaseOpenedEvent"
-      factory=".bootstrap.bootStrapSubscriber"
+      handler=".bootstrap.bootStrapSubscriber"
       />
 
   <include file="browser.zcml" />

Modified: Zope3/branches/srichter-blow-services/src/zope/app/session/design.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/session/design.txt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/session/design.txt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -6,7 +6,7 @@
 associate an identifier with a particular client. Whenever we get a
 request from that client, we compute the identifier and use the
 identifier to look up associated information, which is stored on the
-server. 
+server.
 
 A major disadvantage of sessions is that they require management of
 information on the server. This can have major implications for
@@ -20,7 +20,7 @@
 Sessions introduce a number of issues to be considered:
 
 - Clients have to be identified. A number of approaches are possible,
-  including: 
+  including:
 
   o Using HTTP cookies. The application assigns a client identifier,
     which is stored in a cookie.  This technique is the most
@@ -68,7 +68,7 @@
 
   If you know that scalability is not (and never will be) an issue,
   you can just use the object database.
- 
+
   If you have client data that needs to be updated often (as in every
   request), consider storing the data on the client.  (Like all data
   received from a client, it may be tainted and, in most instances,
@@ -145,4 +145,4 @@
 determined by the session data type interface.
 `IPersistentSessionData` defines the application data to be a mapping
 object by default.  Other data interfaces could specify different
-bahavior.  
+bahavior.

Modified: Zope3/branches/srichter-blow-services/src/zope/app/testing/functional.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/testing/functional.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/testing/functional.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -24,31 +24,30 @@
 import traceback
 import unittest
 import urllib
-
 from StringIO import StringIO
 from Cookie import SimpleCookie
-
 from transaction import abort, commit
 from ZODB.DB import DB
 from ZODB.DemoStorage import DemoStorage
-import zope.interface
+
+from zope import interface, component
 from zope.publisher.browser import BrowserRequest
 from zope.publisher.http import HTTPRequest
 from zope.publisher.publish import publish
 from zope.publisher.xmlrpc import XMLRPCRequest
 from zope.security.interfaces import Forbidden, Unauthorized
 from zope.security.management import endInteraction
-import zope.publisher.interfaces.http
 from zope.testing import doctest
 
 import zope.app.pluggableauth
 import zope.app.testing.setup
-
 from zope.app import zapi
 from zope.app.debug import Debugger
 from zope.app.publication.http import HTTPPublication
 from zope.app.publication.browser import BrowserPublication
 from zope.app.publication.xmlrpc import XMLRPCPublication
+from zope.app.publication.soap import SOAPPublication
+from zope.app.publication.interfaces import ISOAPRequestFactory
 from zope.app.publication.zopepublication import ZopePublication
 from zope.app.publication.http import HTTPPublication
 from zope.publisher.interfaces.browser import IDefaultBrowserLayer
@@ -94,18 +93,17 @@
     skin = adapters.lookup((IBrowserRequest,), IDefaultSkin, '')
     return skin or IDefaultBrowserLayer
 
+class IManagerSetup(zope.interface.Interface):
+    """Utility for enabling up a functional testing manager with needed grants
 
-grant_request = (r"""
-POST /@@grant.html HTTP/1.1
-Authorization: Basic Z2xvYmFsbWdyOmdsb2JhbG1ncnB3
-Content-Length: 5796
-Content-Type: application/x-www-form-urlencoded
+    XXX This is an interim solution.  It tries to break the dependence
+    on a particular security policy, however, we need a much better
+    way of managing functional-testing configurations.    
+    """
 
-field.principal=em9wZS5tZ3I_"""
-"""&field.principal.displayed=y"""
-"""&GRANT_SUBMIT=Change"""
-"""&field.em9wZS5tZ3I_.role.zope.Manager=allow"""
-"""&field.em9wZS5tZ3I_.role.zope.Manager-empty-marker=1""")
+    def setUpManager():
+        """Set up the manager, zope.mgr
+        """
 
 class FunctionalTestSetup(object):
     """Keeps shared state across several functional test cases."""
@@ -138,22 +136,10 @@
             self._init = True
 
             # Make a local grant for the test user
-            # TODO, find a better way to make this grant happen.
-            # The way I did this is way too messy, given how
-            # strang FunctionalTestSetup is.  Later, when we
-            # have time, we should clean up this (perhaps with an
-            # event) and clean up FunctionalTestSetup.
-
-            response = http(grant_request, handle_errors=False)
-
-            # XXX: Remove?
-            #from zope.app.securitypolicy.interfaces import IPrincipalRoleManager
-            #root = self.db.open().root()[ZopePublication.root_name]
-            #principal_roles = IPrincipalRoleManager(root)
-            #principal_roles.assignRoleToPrincipal('zope.Manager', 'zope.mgr')
-            #commit()
-            #self.db.close()
-
+            setup = component.queryUtility(IManagerSetup)
+            if setup is not None:
+                setup.setUpManager()
+            
             FunctionalTestSetup().connection = None
             
         elif config_file and config_file != self._config_file:
@@ -214,17 +200,39 @@
     def abort(self):
         abort()
 
-class BrowserTestCase(FunctionalTestCase):
-    """Functional test case for Browser requests."""
 
-    def setUp(self):
-        super(BrowserTestCase, self).setUp()
+class CookieHandler(object):
+
+    def __init__(self, *args, **kw):
         # Somewhere to store cookies between consecutive requests
         self.cookies = SimpleCookie()
+        super(CookieHandler, self).__init__(*args, **kw)
 
+
+    def httpCookie(self, path):
+         """Return self.cookies as an HTTP_COOKIE environment value."""
+         l = [m.OutputString() for m in self.cookies.values()
+              if path.startswith(m['path'])]
+         return '; '.join(l)
+
+    def loadCookies(self, envstring):
+        self.cookies.load(envstring)
+
+    def saveCookies(self, response):
+        """Save cookies from the response."""
+        # Urgh - need to play with the response's privates to extract
+        # cookies that have been set
+        for k,v in response._cookies.items():
+            k = k.encode('utf8')
+            self.cookies[k] = v['value'].encode('utf8')
+            if self.cookies[k].has_key('Path'):
+                self.cookies[k]['Path'] = v['Path']
+
+                 
+class BrowserTestCase(CookieHandler, FunctionalTestCase):
+    """Functional test case for Browser requests."""
+
     def tearDown(self):
-        del self.cookies
-
         self.setSite(None)
         super(BrowserTestCase, self).tearDown()
 
@@ -255,22 +263,16 @@
             outstream = HTTPTaskStub()
         environment = {"HTTP_HOST": 'localhost',
                        "HTTP_REFERER": 'localhost',
-                       "HTTP_COOKIE": self.__http_cookie(path)}
+                       "HTTP_COOKIE": self.httpCookie(path)}
         environment.update(env)
         app = FunctionalTestSetup().getApplication()
         request = app._request(path, '', outstream,
                                environment=environment,
                                basic=basic, form=form,
                                request=BrowserRequest)
-        zope.interface.directlyProvides(request, _getDefaultSkin())
+        interface.directlyProvides(request, _getDefaultSkin())
         return request
 
-    def __http_cookie(self, path):
-        '''Return self.cookies as an HTTP_COOKIE environment format string'''
-        l = [m.OutputString() for m in self.cookies.values()
-                if path.startswith(m['path'])]
-        return '; '.join(l)
-
     def publish(self, path, basic=None, form=None, env={},
                 handle_errors=False):
         """Renders an object at a given location.
@@ -293,22 +295,16 @@
         # We pull it apart and reassemble the header to block cookies
         # with invalid paths going through, which may or may not be correct
         if env.has_key('HTTP_COOKIE'):
-            self.cookies.load(env['HTTP_COOKIE'])
+            self.loadCookies(env['HTTP_COOKIE'])
             del env['HTTP_COOKIE'] # Added again in makeRequest
 
         request = self.makeRequest(path, basic=basic, form=form, env=env,
                                    outstream=outstream)
         response = ResponseWrapper(request.response, outstream, path)
         if env.has_key('HTTP_COOKIE'):
-            self.cookies.load(env['HTTP_COOKIE'])
+            self.loadCookies(env['HTTP_COOKIE'])
         publish(request, handle_errors=handle_errors)
-        # Urgh - need to play with the response's privates to extract
-        # cookies that have been set
-        for k,v in response._cookies.items():
-            k = k.encode('utf8')
-            self.cookies[k] = v['value'].encode('utf8')
-            if self.cookies[k].has_key('Path'):
-                self.cookies[k]['Path'] = v['Path']
+        self.saveCookies(response)
         self.setSite(old_site)
         return response
 
@@ -433,7 +429,7 @@
 
 class HTTPHeaderOutput:
 
-    zope.interface.implements(zope.publisher.interfaces.http.IHeaderOutput)
+    interface.implements(zope.publisher.interfaces.http.IHeaderOutput)
 
     def __init__(self, protocol, omit):
         self.headers = {}
@@ -483,83 +479,8 @@
     def getBody(self):
         return self.getOutput()
 
-def http(request_string, handle_errors=True):
-    """Execute an HTTP request string via the publisher
 
-    This is used for HTTP doc tests.
-    """
-    # Commit work done by previous python code.
-    commit()
-
-    # Discard leading white space to make call layout simpler
-    request_string = request_string.lstrip()
-
-    # split off and parse the command line
-    l = request_string.find('\n')
-    command_line = request_string[:l].rstrip()
-    request_string = request_string[l+1:]
-    method, path, protocol = command_line.split()
-    path = urllib.unquote(path)
-    
-
-    instream = StringIO(request_string)
-    environment = {"HTTP_HOST": 'localhost',
-                   "HTTP_REFERER": 'localhost',
-                   "REQUEST_METHOD": method,
-                   "SERVER_PROTOCOL": protocol,
-                   }
-
-    headers = [split_header(header)
-               for header in rfc822.Message(instream).headers]
-    for name, value in headers:
-        name = ('_'.join(name.upper().split('-')))
-        if name not in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
-            name = 'HTTP_' + name
-        environment[name] = value.rstrip()
-
-    auth_key = 'HTTP_AUTHORIZATION'
-    if environment.has_key(auth_key):
-        environment[auth_key] = auth_header(environment[auth_key])
-
-    outstream = HTTPTaskStub()
-
-
-    old_site = getSite()
-    setSite(None)
-    app = FunctionalTestSetup().getApplication()
-    header_output = HTTPHeaderOutput(
-        protocol, ('x-content-type-warning', 'x-powered-by'))
-
-    if method in ('GET', 'POST', 'HEAD'):
-        if (method == 'POST' and
-            environment.get('CONTENT_TYPE', '').startswith('text/xml')
-            ):
-            request_cls = XMLRPCRequest
-            publication_cls = XMLRPCPublication
-        else:
-            request_cls = type(BrowserRequest.__name__, (BrowserRequest,), {})
-            zope.interface.classImplements(request_cls, _getDefaultSkin())
-            publication_cls = BrowserPublication
-    else:
-        request_cls = HTTPRequest
-        publication_cls = HTTPPublication
-    
-    request = app._request(path, instream, outstream,
-                           environment=environment,
-                           request=request_cls, publication=publication_cls)
-    request.response.setHeaderOutput(header_output)
-    response = DocResponseWrapper(request.response, outstream, path,
-                                  header_output)
-    
-    publish(request, handle_errors=handle_errors)
-    setSite(old_site)
-
-    # sync Python connection:
-    getRootFolder()._p_jar.sync()
-    
-    return response
-
-headerre = re.compile('(\S+): (.+)$')
+headerre = re.compile(r'(\S+): (.+)$')
 def split_header(header):
     return headerre.match(header).group(1, 2)
 
@@ -612,9 +533,99 @@
     suite.addTest(unittest.makeSuite(SampleFunctionalTest))
     return suite
 
+
+class HTTPCaller(CookieHandler):
+    """Execute an HTTP request string via the publisher"""
+
+    def __call__(self, request_string, handle_errors=True):
+        # Commit work done by previous python code.
+        commit()
+
+        # Discard leading white space to make call layout simpler
+        request_string = request_string.lstrip()
+
+        # split off and parse the command line
+        l = request_string.find('\n')
+        command_line = request_string[:l].rstrip()
+        request_string = request_string[l+1:]
+        method, path, protocol = command_line.split()
+        path = urllib.unquote(path)
+
+        instream = StringIO(request_string)
+        environment = {"HTTP_COOKIE": self.httpCookie(path),
+                       "HTTP_HOST": 'localhost',
+                       "HTTP_REFERER": 'localhost',
+                       "REQUEST_METHOD": method,
+                       "SERVER_PROTOCOL": protocol,
+                       }
+
+        headers = [split_header(header)
+                   for header in rfc822.Message(instream).headers]
+        for name, value in headers:
+            name = ('_'.join(name.upper().split('-')))
+            if name not in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
+                name = 'HTTP_' + name
+            environment[name] = value.rstrip()
+
+        auth_key = 'HTTP_AUTHORIZATION'
+        if environment.has_key(auth_key):
+            environment[auth_key] = auth_header(environment[auth_key])
+
+        outstream = HTTPTaskStub()
+
+        old_site = getSite()
+        setSite(None)
+        app = FunctionalTestSetup().getApplication()
+        header_output = HTTPHeaderOutput(
+            protocol, ('x-content-type-warning', 'x-powered-by'))
+
+        content_type = environment.get('CONTENT_TYPE', '')
+        is_xml = content_type.startswith('text/xml')
+
+        if method in ('GET', 'POST', 'HEAD'):
+            if (method == 'POST' and environment.get('HTTP_SOAPACTION', None)
+                and is_xml):
+                factory = zapi.queryUtility(ISOAPRequestFactory)
+                if factory is not None:
+                    request_cls = factory(StringIO(), StringIO(), {}).__class__
+                    publication_cls = SOAPPublication
+                else:
+                    request_cls = BrowserRequest
+                    publication_cls = BrowserPublication
+            elif (method == 'POST' and is_xml):
+                request_cls = XMLRPCRequest
+                publication_cls = XMLRPCPublication
+            else:
+                request_cls = BrowserRequest
+                publication_cls = BrowserPublication
+            
+        else:
+            request_cls = HTTPRequest
+            publication_cls = HTTPPublication
+
+        request = app._request(
+            path, instream, outstream,
+            environment=environment,
+            request=request_cls, publication=publication_cls)
+        if request_cls is BrowserRequest:
+            # Only browser requests have skins
+            interface.directlyProvides(request, _getDefaultSkin())
+        request.response.setHeaderOutput(header_output)
+        response = DocResponseWrapper(
+            request.response, outstream, path, header_output)
+
+        publish(request, handle_errors=handle_errors)
+        self.saveCookies(response)
+        setSite(old_site)
+
+        # sync Python connection:
+        getRootFolder()._p_jar.sync()
+
+        return response
+
 def FunctionalDocFileSuite(*paths, **kw):
     globs = kw.setdefault('globs', {})
-    globs['http'] = http
+    globs['http'] = HTTPCaller()
     globs['getRootFolder'] = getRootFolder
     globs['sync'] = sync
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/testing/setup.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/testing/setup.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/testing/setup.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -65,6 +65,16 @@
                          Dependable)
 
 #------------------------------------------------------------------------
+# Registrations
+
+from zope.app.component.interfaces.registration import IComponentRegistration
+from zope.app.component.interfaces.registration import IRegistrationEvent
+from zope.app.component.registration import componentRegistrationEventNotify
+def setUpRegistered():
+    ztapi.subscribe((IComponentRegistration, IRegistrationEvent), None,
+                     componentRegistrationEventNotify)
+
+#------------------------------------------------------------------------
 # Traversal
 from zope.app.traversing.browser.interfaces import IAbsoluteURL
 from zope.app.container.traversal import ContainerTraversable
@@ -120,6 +130,7 @@
     zope.app.component.hooks.setHooks()
     setUpAnnotations()
     setUpDependable()
+    setUpRegistered()
     setUpTraversal()
     setUpSiteManagerLookup()
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/traversing/namespace.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/traversing/namespace.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/traversing/namespace.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -449,7 +449,7 @@
            """
         try:
             return capi.getAdapter(self.context, IPathAdapter, name)
-        except:
+        except ComponentLookupError:
             raise TraversalError(self.context, name)
 
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/undo/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/undo/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/undo/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -20,7 +20,7 @@
 
 
   <subscriber
-      factory=".undoSetup"
+      handler=".undoSetup"
       for="zope.app.appsetup.IDatabaseOpenedEvent"
       />
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/utility/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/utility/__init__.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/utility/__init__.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -14,5 +14,5 @@
 $Id: __init__.py 25177 2004-06-02 13:17:31Z jim $
 """
 
-from utility import UtilityRegistration, LocalUtilityService
-
+from utility import LocalUtilityService
+from zope.app.component.site import UtilityRegistration

Modified: Zope3/branches/srichter-blow-services/src/zope/app/versioncontrol/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/versioncontrol/tests.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/versioncontrol/tests.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -19,31 +19,19 @@
 import unittest
 
 from zope.component.tests.placelesssetup import PlacelessSetup
-from zope.testing import doctest
+from zope.testing import doctest, module
 from transaction import abort
 
-class FakeModule:
-    def __init__(self, dict):
-        self.__dict = dict
-    def __getattr__(self, name):
-        try:
-            return self.__dict[name]
-        except KeyError:
-            raise AttributeError, name
-
 name = 'zope.app.versioncontrol.README'
 
 ps = PlacelessSetup()
 
 def setUp(test):
     ps.setUp()
-    dict = test.globs
-    dict.clear()
-    dict['__name__'] = name    
-    sys.modules[name] = FakeModule(dict)
+    module.setUp(test, name)
 
 def tearDown(test):
-    del sys.modules[name]
+    module.tearDown(test, name)
     abort()
     db = test.globs.get('db')
     if db is not None:

Copied: Zope3/branches/srichter-blow-services/src/zope/app/wfmc (from rev 29088, Zope3/trunk/src/zope/app/wfmc)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/wfmc/__init__.py
===================================================================
--- Zope3/trunk/src/zope/app/wfmc/__init__.py	2005-02-09 01:00:34 UTC (rev 29088)
+++ Zope3/branches/srichter-blow-services/src/zope/app/wfmc/__init__.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -1 +1 @@
-#
+# Make a package.

Modified: Zope3/branches/srichter-blow-services/src/zope/app/wfmc/metaconfigure.py
===================================================================
--- Zope3/trunk/src/zope/app/wfmc/metaconfigure.py	2005-02-09 01:00:34 UTC (rev 29088)
+++ Zope3/branches/srichter-blow-services/src/zope/app/wfmc/metaconfigure.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -1,3 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
 """WFMC metaconfigure
 
 $Id: $
@@ -2,25 +15,12 @@
 """
-
-import zope.interface
-import zope.schema
-import zope.configuration.fields
-import zope.component
-
-from zope.app import zapi
+__docformat__ = "reStructuredText"
 from zope import wfmc
 from zope.wfmc import xpdl
+from zope.app.component.metaconfigure import utility
 
-def createUtility(file, process, id):
+def defineXpdl(_context, file, process, id):
     package = xpdl.read(open(file))
     definition = package[process]
     definition.id = id
 
-    zapi.getGlobalService('Utilities').provideUtility(
-            wfmc.interfaces.IProcessDefinition, definition, id)
-
-def defineXpdl(_context, file, process, id):
-    _context.action(
-        discriminator=('intranet:xpdl', id),
-        callable=createUtility, 
-        args=(file, process, id),
-        )
+    utility(_context, wfmc.interfaces.IProcessDefinition, definition, name=id)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/wfmc/metadirectives.py
===================================================================
--- Zope3/trunk/src/zope/app/wfmc/metadirectives.py	2005-02-09 01:00:34 UTC (rev 29088)
+++ Zope3/branches/srichter-blow-services/src/zope/app/wfmc/metadirectives.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -1,3 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
 """ZCML directives for defining privileges.
 
 $Id: $
@@ -2,3 +15,3 @@
 """
-
+__docformat__ = "reStructuredText"
 import zope.interface

Modified: Zope3/branches/srichter-blow-services/src/zope/app/wfmc/tests.py
===================================================================
--- Zope3/trunk/src/zope/app/wfmc/tests.py	2005-02-09 01:00:34 UTC (rev 29088)
+++ Zope3/branches/srichter-blow-services/src/zope/app/wfmc/tests.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -1,16 +1,32 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""WFMC Tests Setup
+
+$Id$
 """
-$Id: $
-"""
+__docformat__ = "reStructuredText"
 import os
 import unittest
 
-import zope
-from zope.app.tests import placelesssetup
 from zope.configuration import xmlconfig
-from zope.app.tests import ztapi
+from zope.testing import module, doctest
+
 import zope.app.annotation.interfaces
 import zope.app.annotation.attribute
-from zope.testing import module
+import zope.app.wfmc
+from zope.app.tests import placelesssetup
+from zope.app.tests import ztapi
 
 def zcml(s):
     context = xmlconfig.file('meta.zcml', package=zope.app.wfmc)
@@ -21,7 +37,6 @@
     placelesssetup.setUp(test)
 
 def test_suite():
-    from zope.testing import doctest
     return doctest.DocFileSuite(
                 'zcml.txt', globs={'zcml': zcml},
                 setUp=setUp,

Modified: Zope3/branches/srichter-blow-services/src/zope/app/workflow/stateful/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/workflow/stateful/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/app/workflow/stateful/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -125,7 +125,7 @@
 <subscriber
    for="..interfaces.IProcessInstanceContainerAdaptable
         zope.app.event.objectevent.IObjectCreatedEvent"
-   factory=".contentworkflow.NewObjectProcessInstanceCreator"
+   handler=".contentworkflow.NewObjectProcessInstanceCreator"
    />
 
 <!-- Test Object for testing Stateful Workflows -->

Copied: Zope3/branches/srichter-blow-services/src/zope/bforest (from rev 29088, Zope3/trunk/src/zope/bforest)

Modified: Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/README.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/README.txt	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/README.txt	2005-02-10 15:21:18 UTC (rev 29102)
@@ -1 +1,24 @@
-See __init__.py.
+Cached descriptors
+
+Cached descriptors cache their output.  They take into account
+instance attributes that they depend on, so when the instance
+attributes change, the descriptors will change the values they
+return.
+
+Cached descriptors cache their data in _v_ attributes, so they are
+also useful for managing the computation of volatile attributes for
+persistent objects.
+
+Persistent descriptors:
+
+  property
+
+     A simple computed property. See property.txt.
+
+  method
+
+     Idempotent method.  The return values are cached based on method
+     arguments and on any instance attributes that the methods are
+     defined to depend on.
+
+     **Note**, methods haven't been implemented yet.

Modified: Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/__init__.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/__init__.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -1,40 +1 @@
-##############################################################################
 #
-# Copyright (c) 2004 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.
-#
-##############################################################################
-"""Cached descriptors
-
-Cached descriptors cache their output.  They take into account
-instance attributes that they depend on, so when the instance
-attributes change, the descriptors will change the values they
-return.
-
-Cached descriptors cache their data in _v_ attributes, so they are
-also useful for managing the computation of volatile attributes for
-persistent objects.
-
-Persistent descriptors:
-
-  property
-
-     A simple computed property
-
-  method
-
-     Idempotent method.  The return values are cached based on method
-     arguments and on any instance attributes that the methods are
-     defined to depend on.
-
-     **Note**, methods haven't been implemented yet.
-
-$Id$
-"""

Modified: Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/property.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/property.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/property.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -19,35 +19,6 @@
 
 class CachedProperty(object):
     """Cached Properties
-
-    Cached properties are computed properties that cache their computed
-    values.  They take into account instance attributes that they depend
-    on, so when the instance attributes change, the properties will change
-    the values they return.
-    
-    Cached properties cache their data in _v_ attributes, so they are
-    also useful for managing the computation of volatile attributes for
-    persistent objects.
-
-    Example::
-
-      from persistent import Persistent 
-      from zope.cachedescriptors.property import CachedProperty
-
-      class FileManager(Persistent):
-
-         def __init__(self, filename):
-             self.filename = filename
-
-         def file(self):
-             return open(self.filename)
-
-         file = CachedProperty(file, 'filename')
-
-      file_manager = FileManager('data.txt')
-
-      x = file_manager.file.read(10)
-
     """
 
     def __init__(self, func, *names):
@@ -79,3 +50,23 @@
         setattr(inst, value_name, value)
         
         return value
+
+
+class Lazy(object):
+    """Lazy Attributes
+    """
+
+    def __init__(self, func, name=None):
+        if name is None:
+            name = func.__name__
+        self.data = (func, name)
+
+    def __get__(self, inst, class_):
+        if inst is None:
+            return self
+
+        func, name = self.data
+        value = func(inst)
+        inst.__dict__[name] = value
+        
+        return value

Copied: Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/property.txt (from rev 29098, Zope3/trunk/src/zope/cachedescriptors/property.txt)


Property changes on: Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/property.txt
___________________________________________________________________
Name: cvs2svn:cvs-rev
   + 1.2
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Copied: Zope3/branches/srichter-blow-services/src/zope/cachedescriptors/tests.py (from rev 29098, Zope3/trunk/src/zope/cachedescriptors/tests.py)

Modified: Zope3/branches/srichter-blow-services/src/zope/configuration/tests/test_config.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/configuration/tests/test_config.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/configuration/tests/test_config.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -197,7 +197,7 @@
     """
     #'
 
-def test_kyeword_handling():
+def test_keyword_handling():
     """
     >>> machine = ConfigurationMachine()
     >>> ns = "http://www.zope.org/testing"

Modified: Zope3/branches/srichter-blow-services/src/zope/interface/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/interface/__init__.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/interface/__init__.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -50,6 +50,7 @@
 
 $Id$
 """
+__docformat__ = 'restructuredtext'
 
 from zope.interface.interface import Interface, _wire
 

Modified: Zope3/branches/srichter-blow-services/src/zope/interface/declarations.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/interface/declarations.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/interface/declarations.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -26,6 +26,7 @@
 
 $Id$
 """
+__docformat__ = 'restructuredtext'
 import sys
 import weakref
 from zope.interface.interface import InterfaceClass, Specification

Modified: Zope3/branches/srichter-blow-services/src/zope/interface/interfaces.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/interface/interfaces.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/interface/interfaces.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -15,7 +15,9 @@
 
 $Id$
 """
+__docformat__ = 'restructuredtext'
 
+
 from zope.interface import Interface
 from zope.interface.interface import Attribute
 

Modified: Zope3/branches/srichter-blow-services/src/zope/schema/_bootstrapfields.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/schema/_bootstrapfields.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/schema/_bootstrapfields.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -15,6 +15,7 @@
 
 $Id$
 """
+__docformat__ = 'restructuredtext'
 from zope.interface import Attribute, providedBy, implements
 from zope.schema._bootstrapinterfaces import StopValidation
 from zope.schema._bootstrapinterfaces import IFromUnicode
@@ -181,6 +182,7 @@
                                object.__class__.__name__))
         setattr(object, self.__name__, value)
 
+
 class Container(Field):
 
     def _validate(self, value):

Modified: Zope3/branches/srichter-blow-services/src/zope/schema/_field.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/schema/_field.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/schema/_field.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -17,7 +17,6 @@
 $Id$
 """
 __docformat__ = 'restructuredtext'
-
 import warnings
 import re
 from datetime import datetime, date
@@ -179,8 +178,6 @@
 
     def __init__(self, values=None, vocabulary=None, source=None, **kw):
         """Initialize object."""
-
-
         if vocabulary is not None:
             assert (isinstance(vocabulary, basestring)
                     or IVocabulary.providedBy(vocabulary))
@@ -189,12 +186,12 @@
         elif source is not None:
             assert ISource.providedBy(source)
             vocabulary = source
-        
+
         assert not (values is None and vocabulary is None), (
                "You must specify either values or vocabulary.")
         assert values is None or vocabulary is None, (
                "You cannot specify both values and vocabulary.")
-        
+
         self.vocabulary = None
         self.vocabularyName = None
         if values is not None:
@@ -238,7 +235,7 @@
         """
         self.validate(str)
         return str
-        
+
     def _validate(self, value):
         # Pass all validations during initialization
         if self._init_field:
@@ -265,29 +262,29 @@
 
 def _validate_sequence(value_type, value, errors=None):
     """Validates a sequence value.
-    
+
     Returns a list of validation errors generated during the validation. If
     no errors are generated, returns an empty list.
-    
+
     value_type is a field. value is the sequence being validated. errors is
     an optional list of errors that will be prepended to the return value.
-    
+
     To illustrate, we'll use a text value type. All values must be unicode.
-    
+
 	    >>> field = TextLine(required=True)
-	
+
 	To validate a sequence of various values:
-	
+
 	    >>> errors = _validate_sequence(field, ('foo', u'bar', 1))
 	    >>> errors
 	    [foo <type 'unicode'>, 1 <type 'unicode'>]
-	
+
 	The only valid value in the sequence is the second item. The others
 	generated errors.
-	
+
 	We can use the optional errors argument to collect additional errors
 	for a new sequence:
-	
+
         >>> errors = _validate_sequence(field, (2, u'baz'), errors)
         >>> errors
         [foo <type 'unicode'>, 1 <type 'unicode'>, 2 <type 'unicode'>]
@@ -312,7 +309,7 @@
 
         temp_values.append(item)
 
-class AbstractCollection(MinMaxLen, Iterable, Field):
+class AbstractCollection(MinMaxLen, Iterable):
     value_type = None
     unique = False
 
@@ -330,7 +327,7 @@
         # binding value_type is necessary for choices with named vocabularies,
         # and possibly also for other fields.
         if clone.value_type is not None:
-           clone.value_type = clone.value_type.bind(object) 
+           clone.value_type = clone.value_type.bind(object)
         return clone
 
     def _validate(self, value):
@@ -363,13 +360,13 @@
 
 def _validate_fields(schema, value, errors=None):
     if errors is None:
-        errors = []  
+        errors = []
     for name in schema.names(all=True):
         if not IMethod.providedBy(schema[name]):
             try:
                 attribute = schema[name]
                 if IField.providedBy(attribute):
-                    # validate attributes that are fields  
+                    # validate attributes that are fields
                     attribute.validate(getattr(value, name))
             except ValidationError, error:
                 errors.append(error)
@@ -386,24 +383,24 @@
     def __init__(self, schema, **kw):
         if not IInterface.providedBy(schema):
             raise WrongType
-            
+
         self.schema = schema
         super(Object, self).__init__(**kw)
-        
+
     def _validate(self, value):
         super(Object, self)._validate(value)
-        
+
         # schema has to be provided by value
         if not self.schema.providedBy(value):
             raise SchemaNotProvided
-            
+
         # check the value against schema
         errors = _validate_fields(self.schema, value)
         if errors:
             raise WrongContainedType(errors)
 
 
-class Dict(MinMaxLen, Iterable, Field):
+class Dict(MinMaxLen, Iterable):
     """A field representing a Dict."""
     implements(IDict)
     _type = dict
@@ -587,10 +584,10 @@
         >>> dotted_name = DottedName(__name__='test')
         >>> dotted_name.validate("a.b.c")
         >>> dotted_name.validate("a")
-        >>> dotted_name.validate("   a   ")
+        >>> dotted_name.validate("   a")
         Traceback (most recent call last):
         ...
-        InvalidDottedName:    a   
+        InvalidDottedName:    a
 
         >>> dotted_name = DottedName(__name__='test', min_dots=1)
         >>> dotted_name.validate('a.b')

Modified: Zope3/branches/srichter-blow-services/src/zope/security/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/security/__init__.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/security/__init__.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -22,3 +22,4 @@
 import zope.proxy
 
 from zope.security.management import checkPermission
+from zope.security.checker import canWrite, canAccess

Modified: Zope3/branches/srichter-blow-services/src/zope/security/checker.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/security/checker.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/security/checker.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -84,7 +84,40 @@
 
 directlyProvides(ProxyFactory, ISecurityProxyFactory)
 
+def canWrite(obj, name):
+    """Check whether the interaction may write an attribute named name on obj.
+    
+    Convenience method.  Rather than using checkPermission in high level code,
+    use canWrite and canAccess to avoid binding code to permissions.
+    """
+    obj = ProxyFactory(obj)
+    checker = getChecker(obj)
+    try:
+        checker.check_setattr(obj, name)
+    except Unauthorized:
+        return False
+    # if it is Forbidden (or anything else), let it be raised: it probably 
+    # indicates a programming or configuration error
+    return True
 
+def canAccess(obj, name):
+    """Check whether the interaction may access an attribute named name on obj.
+    
+    Convenience method.  Rather than using checkPermission in high level code,
+    use canWrite and canAccess to avoid binding code to permissions.
+    """
+    # access attributes and methods, including, in the current checker 
+    # implementation, special names like __getitem__
+    obj = ProxyFactory(obj)
+    checker = getChecker(obj)
+    try:
+        checker.check_getattr(obj, name)
+    except Unauthorized:
+        return False
+    # if it is Forbidden (or anything else), let it be raised: it probably 
+    # indicates a programming or configuration error
+    return True
+
 class Checker(object):
     implements(INameBasedChecker)
 
@@ -92,7 +125,7 @@
         """Create a checker
 
         A dictionary must be provided for computing permissions for
-        names. The disctionary get will be called with attribute names
+        names. The dictionary get will be called with attribute names
         and must return a permission id, None, or the special marker,
         CheckerPublic. If None is returned, then access to the name is
         forbidden. If CheckerPublic is returned, then access will be

Modified: Zope3/branches/srichter-blow-services/src/zope/security/interfaces.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/security/interfaces.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/security/interfaces.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -110,16 +110,20 @@
     def check_getattr(ob, name):
         """Check whether attribute access is allowed.
 
+        May raise Unauthorized or Forbidden.  Returns no value.
+
         If a checker implements __setitem__, then __setitem__ will be
-        called rather than check_getattr to chack whether an attribute
+        called rather than check_getattr to check whether an attribute
         access is allowed.  This is a hack that allows significantly
         greater performance due to the fact that low-level operator
         access is much faster than method access.
-        
         """
 
     def check_setattr(ob, name):
-        """Check whether attribute assignment is allowed."""
+        """Check whether attribute assignment is allowed.
+        
+        May raise Unauthorized or Forbidden.  Returns no value.
+        """
 
     def check(ob, operation):
         """Check whether operation is allowed.
@@ -127,12 +131,13 @@
         The operation name is the Python special method name,
         e.g. "__getitem__".
 
+        May raise Unauthorized or Forbidden.  Returns no value.
+
         If a checker implements __setitem__, then __setitem__ will be
         called rather than check to chack whether an operation is
         allowed.  This is a hack that allows significantly greater
         performance due to the fact that low-level operator access is
         much faster than method access.
-        
         """
 
     def proxy(value):
@@ -143,7 +148,6 @@
         that allows significantly greater performance due to the fact
         that low-level operator access is much faster than method
         access.
-
         """
 
 
@@ -279,6 +283,9 @@
         value_type=TextLine(),
         required=False)
 
+class IGroup(IPrincipal):
+    """Group of principals
+    """
                 
 class IPermission(Interface):
     """A permission object."""

Modified: Zope3/branches/srichter-blow-services/src/zope/security/tests/test_checker.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/security/tests/test_checker.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/security/tests/test_checker.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -28,6 +28,7 @@
 from zope.security.proxy import removeSecurityProxy
 from zope.security.proxy import getChecker
 from zope.security.checker import defineChecker, ProxyFactory
+from zope.security.checker import canWrite, canAccess
 from zope.security.proxy import Proxy
 import types, pickle
 
@@ -365,8 +366,67 @@
         proxy1 = ProxyFactory(obj, checker)
         proxy2 = ProxyFactory(proxy1, checker)
         self.assert_(proxy1 is proxy2)
+    
+    def test_canWrite_canAccess(self):
+        # the canWrite and canAccess functions are conveniences.  Often code
+        # wants to check if a certain option is open to a user before 
+        # presenting it.  If the code relies on a certain permission, the
+        # Zope 3 goal of keeping knowledge of security assertions out of the
+        # code and only in the zcml assertions is broken.  Instead, ask if the
+        # current user canAccess or canWrite some pertinent aspect of the 
+        # object.  canAccess is used for both read access on an attribute
+        # and call access to methods.
+        
+        # For example, consider this humble pair of class and object.
+        class SomeClass(object):
+            pass
+        obj = SomeClass()
+        
+        # We will establish a checker for the class.  This is the standard
+        # name-based checker, and works by specifying two dicts, one for read
+        # and one for write.  Each item in the dictionary should be an
+        # attribute name and the permission required to read or write it.  
+        
+        # For these tests, the SecurityPolicy defined at the top of this file 
+        # is in place.  It is a stub.  Normally, the security policy would
+        # have knowledge of interactions and participants, and would determine
+        # on the basis of the particpants and the object if a certain permission
+        # were authorized.  This stub simply says that the 'test_allowed' 
+        # permission is authorized and nothing else is, for any object you pass
+        # it.
+        
+        # Therefore, according to the checker created here, the current 
+        # 'interaction' (as stubbed out in the security policy) will be allowed
+        # to access and write foo, and access bar.  The interaction is 
+        # unauthorized for accessing baz and writing bar.  Any other access or 
+        # write is not merely unauthorized but forbidden--including write access
+        # for baz.
+        checker = Checker(
+            {'foo':'test_allowed',
+             'bar':'test_allowed',
+             'baz':'you_will_not_have_this_permission'},
+            {'foo':'test_allowed',
+             'bar':'you_will_not_have_this_permission'})
+        defineChecker(SomeClass, checker)
+        
+        # so, our hapless interaction may write and access foo...
+        self.assert_(canWrite(obj, 'foo'))
+        self.assert_(canAccess(obj, 'foo'))
+        
+        # ...may access, but not write, bar...
+        self.assert_(not canWrite(obj, 'bar'))
+        self.assert_(canAccess(obj, 'bar'))
+        
+        # ...and may access baz.
+        self.assert_(not canAccess(obj, 'baz'))
+        
+        # there are no security assertions for writing baz or accessing 
+        # anything else, so these actually raise Forbidden.  The rationale
+        # behind exposing the Forbidden exception is primarily that it is
+        # usually indicative of programming or configuration errors.
+        self.assertRaises(Forbidden, canWrite, obj, 'baz')
+        self.assertRaises(Forbidden, canAccess, obj, 'shazam')
 
-
 class TestCheckerPublic(TestCase):
 
     def test_that_pickling_CheckerPublic_retains_identity(self):

Modified: Zope3/branches/srichter-blow-services/src/zope/structuredtext/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/structuredtext/__init__.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/structuredtext/__init__.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -31,3 +31,4 @@
 
 $Id$
 """
+__docformat__ = 'restructuredtext'

Copied: Zope3/branches/srichter-blow-services/src/zope/testing/module.py (from rev 29088, Zope3/trunk/src/zope/testing/module.py)


Property changes on: Zope3/branches/srichter-blow-services/src/zope/testing/module.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: Zope3/branches/srichter-blow-services/src/zope/thread/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/thread/__init__.py	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zope/thread/__init__.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -143,6 +143,7 @@
 
 $Id$
 """
+__docformat__ = 'restructuredtext'
 
 try:
     import _zope_thread

Copied: Zope3/branches/srichter-blow-services/src/zope/wfmc (from rev 29098, Zope3/trunk/src/zope/wfmc)

Modified: Zope3/branches/srichter-blow-services/src/zope/wfmc/tests.py
===================================================================
--- Zope3/trunk/src/zope/wfmc/tests.py	2005-02-10 01:08:08 UTC (rev 29098)
+++ Zope3/branches/srichter-blow-services/src/zope/wfmc/tests.py	2005-02-10 15:21:18 UTC (rev 29102)
@@ -18,22 +18,22 @@
 import os
 import unittest
 import zope.event
-from zope.component.tests import placelesssetup
+from zope.component import testing
 
 def tearDown(test):
-    placelesssetup.tearDown(test)
+    testing.tearDown(test)
     zope.event.subscribers.pop()
 
 def setUp(test):
     test.globs['this_directory'] = os.path.dirname(__file__)
-    placelesssetup.setUp(test)
+    testing.setUp(test)
 
 def test_suite():
     from zope.testing import doctest
     suite = unittest.TestSuite()
     # suite.addTest(doctest.DocTestSuite())
     suite.addTest(doctest.DocFileSuite('README.txt', tearDown=tearDown,
-                                       setUp=placelesssetup.setUp))
+                                       setUp=testing.setUp))
     suite.addTest(doctest.DocFileSuite(
         'xpdl.txt', tearDown=tearDown, setUp=setUp,
         optionflags=doctest.NORMALIZE_WHITESPACE))

Modified: Zope3/branches/srichter-blow-services/src/zwiki/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zwiki/configure.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/src/zwiki/configure.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -261,15 +261,15 @@
 
   <!-- Register event listener for change mails -->
   <subscriber
-      factory=".wikipage.mailer"
+      handler=".wikipage.mailer"
       for="zope.app.container.interfaces.IObjectAddedEvent"
       />
   <subscriber
-      factory=".wikipage.mailer"
+      handler=".wikipage.mailer"
       for="zope.app.container.interfaces.IObjectRemovedEvent"
       />
   <subscriber
-      factory=".wikipage.mailer"
+      handler=".wikipage.mailer"
       for=".interfaces.IWikiPageEditEvent"
       />
 

Modified: Zope3/branches/srichter-blow-services/zopeskel/bin/test.in
===================================================================
--- Zope3/branches/srichter-blow-services/zopeskel/bin/test.in	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/zopeskel/bin/test.in	2005-02-10 15:21:18 UTC (rev 29102)
@@ -1,4 +1,4 @@
-#!<<PYTHON>>
+#!<<PYTHON>> -u
 ##############################################################################
 #
 # Copyright (c) 2004 Zope Corporation and Contributors.

Modified: Zope3/branches/srichter-blow-services/zopeskel/etc/overrides_ftesting.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/zopeskel/etc/overrides_ftesting.zcml	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/zopeskel/etc/overrides_ftesting.zcml	2005-02-10 15:21:18 UTC (rev 29102)
@@ -10,4 +10,4 @@
        <includeOverrides file="overrides.zcml" />
   -->
 
-</configure>
\ No newline at end of file
+</configure>

Modified: Zope3/branches/srichter-blow-services/zopeskel/etc/principals.zcml.in
===================================================================
--- Zope3/branches/srichter-blow-services/zopeskel/etc/principals.zcml.in	2005-02-10 12:44:52 UTC (rev 29101)
+++ Zope3/branches/srichter-blow-services/zopeskel/etc/principals.zcml.in	2005-02-10 15:21:18 UTC (rev 29102)
@@ -8,6 +8,21 @@
     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
     id="zope.manager"
     title="Manager"



More information about the Zope3-Checkins mailing list