[Zope3-checkins] SVN: Zope3/branches/srichter-blow-services/ Merged in changes from trunk. These are necessary, since they remove all

Stephan Richter srichter at cosmos.phy.tufts.edu
Tue Dec 21 11:57:32 EST 2004


Log message for revision 28670:
  Merged in changes from trunk. These are necessary, since they remove all 
  services other than the utility, adapter and service service, which will 
  be removed by the work of this branch.
  
  

Changed:
  _U  Zope3/branches/srichter-blow-services/bin/debugzope
  U   Zope3/branches/srichter-blow-services/doc/CHANGES.txt
  D   Zope3/branches/srichter-blow-services/package-includes/pas-configure.zcml
  A   Zope3/branches/srichter-blow-services/package-includes/pau-configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/appsetup/bootstrap.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/appsetup/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/container/browser/contents.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/container/browser/tests/test_contents.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/container/tests/placelesssetup.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/copypastemove/tests/test_clipboard.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/debugskin/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/event/tests/placelesssetup.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/exception/browser/tests/test_unauthorized.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/exception/browser/unauthorized.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/homefolder/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/i18n/tests/placelesssetup.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/location/traversing.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/pagetemplate/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/pagetemplate/interfaces.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/pagetemplate/talesapi.py
  D   Zope3/branches/srichter-blow-services/src/zope/app/pas/
  A   Zope3/branches/srichter-blow-services/src/zope/app/pau/
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/README.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/__init__.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/browser/ftests.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/browser/groupfolder.zcml
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/browserplugins.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/groupfolder.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/httpplugins.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/idpicker.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/idpicker.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/interfaces.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/pau.py
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/principalfolder.txt
  _U  Zope3/branches/srichter-blow-services/src/zope/app/pau/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/__init__.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/bootstrap.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/configure.zcml
  U   Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/interfaces.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/publication/tests/test_zopepublication.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/publication/zopepublication.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/registration/README.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/registration/interfaces.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/adapter.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/basicauthadapter.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/browser/auth.py
  D   Zope3/branches/srichter-blow-services/src/zope/app/security/browser/authservicesearchview.txt
  A   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
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/browser/principalterms.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/browser/principalterms.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
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/interfaces.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/principal.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/principalregistry.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/tests/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/tests/test_securitydirectives.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/security/vocabulary.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/browser/granting.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_principalpermissionmanager.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_principalrolemanager.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_securitydirectives.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_zopepolicy.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/zopepolicy.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/session/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/site/service.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/site/tests/placefulsetup.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/sqlscript/browser/sqlscript.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/tests/__init__.py
  D   Zope3/branches/srichter-blow-services/src/zope/app/tests/dochttp.py
  D   Zope3/branches/srichter-blow-services/src/zope/app/tests/dochttp.txt
  D   Zope3/branches/srichter-blow-services/src/zope/app/tests/functional.py
  D   Zope3/branches/srichter-blow-services/src/zope/app/tests/placelesssetup.py
  D   Zope3/branches/srichter-blow-services/src/zope/app/tests/recorded/
  D   Zope3/branches/srichter-blow-services/src/zope/app/tests/setup.py
  D   Zope3/branches/srichter-blow-services/src/zope/app/tests/test.py
  D   Zope3/branches/srichter-blow-services/src/zope/app/tests/test_dochttp.py
  D   Zope3/branches/srichter-blow-services/src/zope/app/tests/test_functional.py
  D   Zope3/branches/srichter-blow-services/src/zope/app/tests/ztapi.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/traversing/browser/absoluteurl.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/traversing/browser/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/traversing/namespace.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/traversing/tests/test_presentation.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/traversing/tests/test_skin.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/traversing/tests/test_traverser.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/tree/browser/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/utility/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/utility/utility.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/workflow/tests/workflowsetup.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/zapi/README.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/zapi/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/zapi/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/zopeappgenerations/evolve1.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/zptpage/tests/test_zptpage.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/zptpage/textindex/tests.py
  U   Zope3/branches/srichter-blow-services/src/zope/component/README.txt
  U   Zope3/branches/srichter-blow-services/src/zope/component/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/component/interfaces.py
  U   Zope3/branches/srichter-blow-services/src/zope/component/site.py
  U   Zope3/branches/srichter-blow-services/src/zope/interface/adapter.py
  U   Zope3/branches/srichter-blow-services/src/zope/interface/adapter.txt
  U   Zope3/branches/srichter-blow-services/src/zope/publisher/http.py
  U   Zope3/branches/srichter-blow-services/src/zope/publisher/tests/test_http.py
  U   Zope3/branches/srichter-blow-services/src/zope/security/untrustedinterpreter.txt
  U   Zope3/branches/srichter-blow-services/src/zope/tales/interfaces.py
  U   Zope3/branches/srichter-blow-services/test.py

-=-

Property changes on: Zope3/branches/srichter-blow-services/bin/debugzope
___________________________________________________________________
Name: svn:keywords
   + Id

Modified: Zope3/branches/srichter-blow-services/doc/CHANGES.txt
===================================================================
--- Zope3/branches/srichter-blow-services/doc/CHANGES.txt	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/doc/CHANGES.txt	2004-12-21 16:57:29 UTC (rev 28670)
@@ -10,6 +10,11 @@
 
     New features
 
+      - 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 `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
@@ -164,8 +169,16 @@
       - Removal of Services.
 
         + Converted Error Reporting Service to a utility. Added database
-          evolution code to convert all serice instances to utilities.
+          evolution code to convert all service instances to utilities.
 
+        + Converted Authentication Service to be a utility. Renamed PAS to
+          PAU.
+
+        + Converted Principal Annotation Service to be a utility. Added
+          database evolution code to convert all service instances to
+          utilities.
+ 
+
       - The `pluggableauth` package has been deprecated. The `pas` module
         provides a much more modular approach with many more capabilities.
 
@@ -254,6 +267,9 @@
 
     Bug Fixes
 
+      - Fixed a bug in the adapter registry that would prevent `dict`-derived
+        utilites from being retrieved correctly.
+
       - Resolved issue 304 (Slash involve dbname). We require now that all
         values in a DSN are properly URL-encoded, so that all values can
         contain any special character, except for the hostname and the port.
@@ -287,11 +303,18 @@
       - Small but important fix to security map. It was not marking objects
         with modified permissions as changed, due to a missing assignment.
 
+      - Contents/contents.pt didn't quote the values that were used in
+        href:s, thus it couldn't function properly if the items contained
+        certain characters.
+
+      - If the content-type was text/*, HTTPResponse.write re-set the
+        content-length header to the first chunk of data.
+
     Much thanks to everyone who contributed to this release:
 
       Jim Fulton, Fred Drake, Philipp von Weitershausen, Stephan Richter,
       Gustavo Niemeyer, Daniel Nouri, Volker Bachschneider, Roger Ineichen,
-      Shane Hathaway
+      Shane Hathaway, Bjorn Tillenius
 
       Note: If you are not listed and contributed, please add yourself. This
       note will be deleted before the release.

Deleted: Zope3/branches/srichter-blow-services/package-includes/pas-configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/package-includes/pas-configure.zcml	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/package-includes/pas-configure.zcml	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1 +0,0 @@
-<include package="zope.app.pas" />
\ No newline at end of file

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


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

Modified: Zope3/branches/srichter-blow-services/src/zope/app/appsetup/bootstrap.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/appsetup/bootstrap.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/appsetup/bootstrap.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -30,20 +30,12 @@
 from zope.app.traversing.api import traverse, traverseName
 from zope.app.publication.zopepublication import ZopePublication
 from zope.app.folder import rootFolder
-from zope.app.servicenames import PrincipalAnnotation
 from zope.app.servicenames import Utilities
 from zope.app.site.service import ServiceManager, ServiceRegistration
 from zope.app.container.interfaces import INameChooser
 from zope.app.utility import UtilityRegistration, LocalUtilityService
 from zope.app.utility.interfaces import ILocalUtilityService
 
-# XXX It should be possible to remove each of these from the basic
-# bootstrap, at which point we can remove the
-# zope.app.principalannotation packages from
-# zope.app.
-
-from zope.app.principalannotation import PrincipalAnnotationService
-
 def ensureObject(root_folder, object_name, object_type, object_factory):
     """Check that there's a basic object in the service
     manager. If not, add one.
@@ -144,10 +136,10 @@
     return name
 
 def addUtility(root_folder, utility_type, utility_factory, **kw):
-    """ Add a Utility to the root folders Utility Service.
+    """ Add a Utility to the root folder's Utility Service.
 
     The utility is added to the default package and activated.
-    This assumes the root folder already as a Utility Service
+    This assumes that the root folder already has a Utility Service.
     """
     package = getServiceManagerDefault(root_folder)
     chooser = INameChooser(package)
@@ -223,8 +215,6 @@
         service_manager = getServiceManager(root_folder)
 
         # Sundry other services
-        ensureService(service_manager, root_folder, PrincipalAnnotation,
-                      PrincipalAnnotationService)
         ensureService(service_manager, root_folder, Utilities,
                       LocalUtilityService)
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/appsetup/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/appsetup/tests.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/appsetup/tests.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -23,7 +23,6 @@
 from zope.app.error.interfaces import IErrorReportingUtility
 from zope.app.folder import rootFolder
 from zope.app.folder.interfaces import IRootFolder
-from zope.app.principalannotation.interfaces import IPrincipalAnnotationService
 from zope.app.publication.zopepublication import ZopePublication
 from zope.app.servicenames import Utilities
 from zope.app.site.service import ServiceManager

Modified: Zope3/branches/srichter-blow-services/src/zope/app/container/browser/contents.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/container/browser/contents.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/container/browser/contents.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -34,6 +34,7 @@
 from zope.app.copypastemove.interfaces import IObjectCopier
 from zope.app.copypastemove.interfaces import IObjectMover
 from zope.app.copypastemove import rename
+from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility
 
 from zope.app.container.browser.adding import Adding
 from zope.app.container.interfaces import IContainer
@@ -266,8 +267,8 @@
         container_path = zapi.getPath(self.context)
 
         user = self.request.principal
-        annotationsvc = zapi.getService('PrincipalAnnotation')
-        annotations = annotationsvc.getAnnotations(user)
+        annotationutil = zapi.getUtility(IPrincipalAnnotationUtility)
+        annotations = annotationutil.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
         clipboard.clearContents()
         items = []
@@ -286,8 +287,8 @@
         container_path = zapi.getPath(self.context)
 
         user = self.request.principal
-        annotationsvc = zapi.getService('PrincipalAnnotation')
-        annotations = annotationsvc.getAnnotations(user)
+        annotationutil = zapi.getUtility(IPrincipalAnnotationUtility)
+        annotations = annotationutil.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
         clipboard.clearContents()
         items = []
@@ -301,8 +302,8 @@
         """
         target = self.context
         user = self.request.principal
-        annotationsvc = zapi.getService('PrincipalAnnotation')
-        annotations = annotationsvc.getAnnotations(user)
+        annotationutil = zapi.getUtility(IPrincipalAnnotationUtility)
+        annotations = annotationutil.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
         items = clipboard.getContents()
         for item in items:
@@ -330,8 +331,8 @@
         """
         target = self.context
         user = self.request.principal
-        annotationsvc = zapi.getService('PrincipalAnnotation')
-        annotations = annotationsvc.getAnnotations(user)
+        annotationutil = zapi.getUtility(IPrincipalAnnotationUtility)
+        annotations = annotationutil.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
         items = clipboard.getContents()
         moved = False
@@ -365,8 +366,8 @@
 
         user = self.request.principal
 
-        annotationsvc = zapi.getService('PrincipalAnnotation')
-        annotations = annotationsvc.getAnnotations(user)
+        annotationutil = zapi.getUtility(IPrincipalAnnotationUtility)
+        annotations = annotationutil.getAnnotations(user)
 
         # touch at least one item to in clipboard confirm contents
         clipboard = IPrincipalClipboard(annotations)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/container/browser/tests/test_contents.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/container/browser/tests/test_contents.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/container/browser/tests/test_contents.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -32,8 +32,8 @@
 from zope.app.copypastemove.interfaces import IPrincipalClipboard
 from zope.app.copypastemove import PrincipalClipboard
 from zope.component import getGlobalServices
-from zope.app.principalannotation import PrincipalAnnotationService
-from zope.app.principalannotation.interfaces import IPrincipalAnnotationService
+from zope.app.principalannotation import PrincipalAnnotationUtility
+from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility
 from zope.app.annotation.interfaces import IAnnotations
 from zope.app.container.contained import contained
 
@@ -56,11 +56,8 @@
 
         ztapi.provideAdapter(IAnnotations, IPrincipalClipboard,
                              PrincipalClipboard)
-        global_sm = getGlobalServices()
-        svc = PrincipalAnnotationService()
-        global_sm.defineService("PrincipalAnnotation", \
-            IPrincipalAnnotationService)
-        global_sm.provideService("PrincipalAnnotation", svc)
+        ztapi.provideUtility(IPrincipalAnnotationUtility,
+                             PrincipalAnnotationUtility())
 
     def testInfo(self):
         # Do we get the correct information back from ContainerContents?
@@ -177,11 +174,8 @@
 
         ztapi.provideAdapter(IAnnotations, IPrincipalClipboard,
                              PrincipalClipboard)
-        global_sm = getGlobalServices()
-        svc = PrincipalAnnotationService()
-        global_sm.defineService("PrincipalAnnotation", \
-            IPrincipalAnnotationService)
-        global_sm.provideService("PrincipalAnnotation", svc)
+        ztapi.provideUtility(IPrincipalAnnotationUtility,
+                             PrincipalAnnotationUtility())
 
     def testRename(self):
         container = traverse(self.rootFolder, 'folder1')

Modified: Zope3/branches/srichter-blow-services/src/zope/app/container/tests/placelesssetup.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/container/tests/placelesssetup.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/container/tests/placelesssetup.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -15,7 +15,7 @@
 
 $Id$
 """
-from zope.app.tests import ztapi
+from zope.app.testing import ztapi
 from zope.app.container.interfaces import IWriteContainer, INameChooser
 from zope.app.container.contained import NameChooser
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/copypastemove/tests/test_clipboard.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/copypastemove/tests/test_clipboard.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/copypastemove/tests/test_clipboard.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -19,8 +19,8 @@
 
 from zope.app import zapi
 from zope.app.tests import ztapi
-from zope.app.principalannotation import PrincipalAnnotationService
-from zope.app.principalannotation.interfaces import IPrincipalAnnotationService
+from zope.app.principalannotation import PrincipalAnnotationUtility
+from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility
 from zope.app.annotation.interfaces import IAnnotations
 
 from zope.app.copypastemove.interfaces import IPrincipalClipboard
@@ -36,17 +36,14 @@
 
         ztapi.provideAdapter(IAnnotations, IPrincipalClipboard,
                              PrincipalClipboard)
-        root_sm = zapi.getGlobalServices()
-        svc = PrincipalAnnotationService()
-        root_sm.defineService("PrincipalAnnotation", \
-            IPrincipalAnnotationService)
-        root_sm.provideService("PrincipalAnnotation", svc)
+        ztapi.provideUtility(IPrincipalAnnotationUtility,
+                             PrincipalAnnotationUtility())
 
     def testAddItems(self):
         user = self._auth['one']['srichter']
 
-        annotationsvc = zapi.getService('PrincipalAnnotation', self)
-        annotations = annotationsvc.getAnnotations(user)
+        annotationutil = zapi.getUtility(IPrincipalAnnotationUtility)
+        annotations = annotationutil.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
         clipboard.addItems('move', ['bla', 'bla/foo', 'bla/bar'])
         expected = ({'action':'move', 'target':'bla'},
@@ -61,8 +58,8 @@
     def testSetContents(self):
         user = self._auth['one']['srichter']
 
-        annotationsvc = zapi.getService('PrincipalAnnotation', self)
-        annotations = annotationsvc.getAnnotations(user)
+        annotationutil = zapi.getUtility(IPrincipalAnnotationUtility)
+        annotations = annotationutil.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
 
         expected = ({'action':'move', 'target':'bla'},
@@ -77,8 +74,8 @@
     def testClearContents(self):
         user = self._auth['one']['srichter']
 
-        annotationsvc = zapi.getService('PrincipalAnnotation', self)
-        annotations = annotationsvc.getAnnotations(user)
+        annotationutil = zapi.getUtility(IPrincipalAnnotationUtility)
+        annotations = annotationutil.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
         clipboard.clearContents()
         self.failUnless(clipboard.getContents() == ())

Modified: Zope3/branches/srichter-blow-services/src/zope/app/debugskin/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/debugskin/configure.zcml	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/debugskin/configure.zcml	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1,6 +1,4 @@
-<zope:configure 
-   xmlns:zope="http://namespaces.zope.org/zope"
-   xmlns="http://namespaces.zope.org/browser">
+<configure xmlns="http://namespaces.zope.org/browser">
 
   <layer name="debug" />
   <skin 
@@ -23,5 +21,4 @@
       permission="zope.Public"
       layer="debug" />
 
-</zope:configure>
-
+</configure>

Modified: Zope3/branches/srichter-blow-services/src/zope/app/event/tests/placelesssetup.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/event/tests/placelesssetup.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/event/tests/placelesssetup.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -19,7 +19,7 @@
 from zope.app.event.objectevent import objectEventNotify
 from zope.interface import implements
 from zope.component import getGlobalServices
-from zope.app.tests import ztapi
+from zope.app.testing import ztapi
 
 events = []
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/exception/browser/tests/test_unauthorized.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/exception/browser/tests/test_unauthorized.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/exception/browser/tests/test_unauthorized.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -19,10 +19,11 @@
 from zope.interface import implements
 from zope.publisher.browser import TestRequest
 from zope.app import zapi
-from zope.app.security.interfaces import IAuthenticationService, IPrincipal
+from zope.app.tests import ztapi
+from zope.app.security.interfaces import IAuthenticationUtility, IPrincipal
 from zope.app.container.contained import contained
 from zope.app.exception.browser.unauthorized import Unauthorized
-from zope.app.event.tests.placelesssetup import PlacelessSetup
+from zope.app.tests.placelesssetup import PlacelessSetup
 
 class Unauthorized(Unauthorized):
     """Unusually done by ZCML."""
@@ -41,8 +42,8 @@
     def getId(self):
         return self.id
 
-class DummyAuthService(object):
-    implements(IAuthenticationService)  # this is a lie
+class DummyAuthUtility(object):
+    implements(IAuthenticationUtility)  # this is a lie
 
     def unauthorized(self, principal_id, request):
         self.principal_id = principal_id
@@ -52,19 +53,17 @@
 class DummyPrincipalSource(object):
     pass
 
-class Test(TestCase, PlacelessSetup):
+class Test(PlacelessSetup, TestCase):
 
     def setUp(self):
         super(Test, self).setUp()
-        self.temp = zapi.getService
-        self.authservice = DummyAuthService()
-        zapi.getService = lambda name: self.authservice
+        self.auth = DummyAuthUtility()
+        ztapi.provideUtility(IAuthenticationUtility, self.auth)
 
     def tearDown(self):
-        zapi.getService = self.temp
         super(Test, self).tearDown()
 
-    def test(self):
+    def testUnauthorized(self):
         exception = Exception()
         try:
             raise exception
@@ -79,10 +78,10 @@
         self.assertEqual(request.response.getStatus(), 403)
 
         # Make sure the auth service was called
-        self.failUnless(self.authservice.request is request)
-        self.assertEqual(self.authservice.principal_id, 23)
+        self.failUnless(self.auth.request is request)
+        self.assertEqual(self.auth.principal_id, 23)
 
-    def testPluggableAuthService(self):
+    def testPluggableAuthUtility(self):
         exception = Exception()
         try:
             raise exception
@@ -98,8 +97,8 @@
         self.assertEqual(request.response.getStatus(), 403)
 
         # Make sure the auth service was called
-        self.failUnless(self.authservice.request is request)
-        self.assertEqual(self.authservice.principal_id, 23)
+        self.failUnless(self.auth.request is request)
+        self.assertEqual(self.auth.principal_id, 23)
 
 def test_suite():
     return makeSuite(Test)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/exception/browser/unauthorized.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/exception/browser/unauthorized.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/exception/browser/unauthorized.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -18,7 +18,6 @@
 __docformat__ = 'restructuredtext'
 
 from zope.app import zapi
-from zope.app.security.interfaces import IAuthenticationService
 
 
 class Unauthorized(object):
@@ -28,5 +27,5 @@
         # challenge the user
         self.request.response.setStatus(403)
         principal = self.request.principal
-        auth = zapi.getService(zapi.servicenames.Authentication)
+        auth = zapi.principals()
         auth.unauthorized(principal.id, self.request)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/homefolder/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/homefolder/tests.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/homefolder/tests.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -11,7 +11,7 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Pluggable Authentication Service Tests
+"""Homefolder Tests
 
 $Id: tests.py 28311 2004-11-01 19:03:56Z jim $
 """

Modified: Zope3/branches/srichter-blow-services/src/zope/app/i18n/tests/placelesssetup.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/i18n/tests/placelesssetup.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/i18n/tests/placelesssetup.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -15,7 +15,7 @@
 
 $Id$
 """
-from zope.app.tests import ztapi
+from zope.app.testing import ztapi
 from zope.i18n.interfaces import IUserPreferredCharsets
 from zope.i18n.interfaces import IUserPreferredLanguages
 from zope.publisher.browser import BrowserLanguages

Modified: Zope3/branches/srichter-blow-services/src/zope/app/location/traversing.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/location/traversing.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/location/traversing.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -73,7 +73,7 @@
         >>> LocationPhysicallyLocatable(o1).getRoot()
         Traceback (most recent call last):
         ...
-        TypeError: Maximim location depth exceeded, """ \
+        TypeError: Maximum location depth exceeded, """ \
                 """probably due to a a location cycle.
         """
         context = self.context
@@ -84,7 +84,7 @@
             context = context.__parent__
             max -= 1
             if max < 1:
-                raise TypeError("Maximim location depth exceeded, "
+                raise TypeError("Maximum location depth exceeded, "
                                 "probably due to a a location cycle.")
 
         raise TypeError("Not enough context to determine location root")

Modified: Zope3/branches/srichter-blow-services/src/zope/app/pagetemplate/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/pagetemplate/configure.zcml	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/pagetemplate/configure.zcml	2004-12-21 16:57:29 UTC (rev 28670)
@@ -6,12 +6,6 @@
 
   <adapter
       for="*"
-      provides=".interfaces.IZopeTalesAPI"
-      factory=".talesapi.ZopeTalesAPI" 
-      />
-
-  <adapter
-      for="*"
       provides="zope.app.traversing.interfaces.IPathAdapter"
       factory=".talesapi.ZopeTalesAPI"
       name="zope" 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/pagetemplate/interfaces.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/pagetemplate/interfaces.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/pagetemplate/interfaces.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -17,33 +17,11 @@
 """
 __docformat__ = 'restructuredtext'
 
-from zope.app.dublincore.interfaces import IDCDescriptiveProperties
-from zope.app.dublincore.interfaces import IDCTimes
-from zope.interface import Interface
+import zope.interface
 
-class IZopeTalesAPI(IDCDescriptiveProperties, IDCTimes):
 
-    def name():
-        """Return the object's name
+class IURLQuote(zope.interface.Interface):
 
-        This is the name the object is stored under in the container
-        it was accessed in.
-        """
-
-    def title_or_name():
-        """Return the title, if the is one, or the name otherwise
-        """
-
-    def size():
-        """Return a string representing the size of the object
-
-        This string could be a collection of digits or a descriptive
-        string of some sort.  If the size can't be determined
-        (e.g. the object has no size), an empty string is returned.
-        """
-    
-class IURLQuote(Interface):
-
     def quote():
         """Return the objects URL quote representation."""
 
@@ -55,4 +33,3 @@
 
     def unquote_plus():
         """Return the objects URL unquote_plus  representation."""
-

Modified: Zope3/branches/srichter-blow-services/src/zope/app/pagetemplate/talesapi.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/pagetemplate/talesapi.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/pagetemplate/talesapi.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -17,17 +17,19 @@
 """
 __docformat__ = 'restructuredtext'
 
+from zope.app.dublincore.interfaces import IDCDescriptiveProperties
+from zope.app.dublincore.interfaces import IDCTimes
 from zope.app.dublincore.interfaces import IZopeDublinCore
 from zope.app.size.interfaces import ISized
 from zope.app import zapi
 from zope.interface import implements
 from zope.security.interfaces import Unauthorized
 from zope.tales.interfaces import ITALESFunctionNamespace
-from interfaces import IZopeTalesAPI
 
+
 class ZopeTalesAPI(object):
 
-    implements(IZopeTalesAPI, ITALESFunctionNamespace)
+    implements(IDCTimes, IDCDescriptiveProperties, ITALESFunctionNamespace)
 
     def __init__(self, context):
         self.context = context
@@ -77,4 +79,3 @@
         if a is None:
             raise AttributeError, 'created'
         return a.sizeForDisplay()
-

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

Modified: Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/__init__.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/__init__.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -11,37 +11,34 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Implementation of `IPrincipalAnnotationService`.
+"""Implementation of `IPrincipalAnnotationUtility`.
 
 $Id$
 """
 __docformat__ = 'restructuredtext'
 
-# TODO: register service as adapter for IAnnotations on service activation
+# TODO: register utility as adapter for IAnnotations on utility activation
 # this depends on existence of LocalAdapterService, so once that's done
 # implement this.
 
-# Zope3 imports
 from persistent import Persistent
 from persistent.dict import PersistentDict
 from BTrees.OOBTree import OOBTree
-from zope.app.component.localservice import queryNextService
-from zope.app.annotation.interfaces import IAnnotations
 from zope.interface import implements
 
-# Sibling imports
-from zope.app.principalannotation.interfaces import IPrincipalAnnotationService
-from zope.app.site.interfaces import ISimpleService
+from zope.app.annotation.interfaces import IAnnotations
 from zope.app.container.contained import Contained
 from zope.app.location import Location
+from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility
+from zope.app.utility.utility import queryNextUtility
 
-class PrincipalAnnotationService(Persistent, Contained):
+class PrincipalAnnotationUtility(Persistent, Contained):
     """Stores `IAnnotations` for `IPrinicipals`.
 
-    The service ID is 'PrincipalAnnotation'.
+    The utility ID is 'PrincipalAnnotation'.
     """
 
-    implements(IPrincipalAnnotationService, ISimpleService)
+    implements(IPrincipalAnnotationUtility)
 
     def __init__(self):
         self.annotations = OOBTree()
@@ -89,10 +86,10 @@
         try:
             return self.data[key]
         except KeyError:
-            # We failed locally: delegate to a higher-level service.
-            service = queryNextService(self, 'PrincipalAnnotation')
-            if service is not None:
-                annotations = service.getAnnotationsById(self.principalId)
+            # We failed locally: delegate to a higher-level utility.
+            utility = queryNextUtility(self, IPrincipalAnnotationUtility)
+            if utility is not None:
+                annotations = utility.getAnnotationsById(self.principalId)
                 return annotations[key]
             raise
 
@@ -114,13 +111,19 @@
 
 class AnnotationsForPrincipal(object):
     """Adapter from IPrincipal to `IAnnotations` for a
-    `PrincipalAnnotationService`.
+    `PrincipalAnnotationUtility`.
 
     Register an *instance* of this class as an adapter.
     """
 
-    def __init__(self, service):
-        self.service = service
+    def __init__(self, utility):
+        self.utility = utility
 
     def __call__(self, principal):
-        return self.service.getAnnotationsById(principal.id)
+        return self.utility.getAnnotationsById(principal.id)
+
+
+#############################################################################
+# BBB: 12/20/2004
+PrincipalAnnotationService = PrincipalAnnotationUtility
+#############################################################################

Copied: Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/bootstrap.py (from rev 28668, Zope3/trunk/src/zope/app/principalannotation/bootstrap.py)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/configure.zcml	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/configure.zcml	2004-12-21 16:57:29 UTC (rev 28670)
@@ -3,26 +3,27 @@
     xmlns:browser="http://namespaces.zope.org/browser"
     >
 
-  <serviceType
-      id="PrincipalAnnotation"
-      interface=".interfaces.IPrincipalAnnotationService" />
-
-  <localService class=".PrincipalAnnotationService">
+  <localUtility class=".PrincipalAnnotationUtility">
     <factory
-        id="zope.app.PrincipalAnnotationService"
+        id="zope.app.PrincipalAnnotationUtility"
         />
     <require
         permission="zope.View"
-        interface=".interfaces.IPrincipalAnnotationService"
+        interface=".interfaces.IPrincipalAnnotationUtility"
         />
-    </localService>
+    </localUtility>
 
-  <!-- Principal annotations (user data) service -->
+  <!-- Principal annotations (user data) utility -->
 
   <browser:addMenuItem
-     class=".PrincipalAnnotationService"
+     class=".PrincipalAnnotationUtility"
      permission="zope.ManageServices"
-     title="Principal Annotation Service"
+     title="Principal Annotation Utility"
      description="Stores Annotations for Principals" />
 
+  <subscriber
+      for="zope.app.appsetup.IDatabaseOpenedEvent"
+      factory=".bootstrap.bootStrapSubscriber"
+      />
+
 </configure>

Modified: Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/interfaces.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/interfaces.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/interfaces.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -20,7 +20,7 @@
 from zope.interface import Interface
 
 
-class IPrincipalAnnotationService(Interface):
+class IPrincipalAnnotationUtility(Interface):
     """Stores `IAnnotations` for `IPrinicipals`."""
 
     def getAnnotations(principal):
@@ -40,3 +40,8 @@
     def hasAnnotations(principal):
         """Return boolean indicating if given `IPrincipal` has
         `IAnnotations`."""
+
+#############################################################################
+# BBB: 12/20/2004
+IPrincipalAnnotationService = IPrincipalAnnotationUtility
+#############################################################################

Modified: Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/tests.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/principalannotation/tests.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -16,16 +16,18 @@
 $Id$
 """
 from unittest import TestCase, TestLoader, TextTestRunner
-from zope.app.site.tests.placefulsetup import PlacefulSetup
-from zope.app.principalannotation import \
-     PrincipalAnnotationService, AnnotationsForPrincipal
-from interfaces import IPrincipalAnnotationService
-from zope.app.tests import ztapi
+from zope import component as capi
+from zope.interface import implements
+from zope.app import zapi
 from zope.app.annotation.interfaces import IAnnotations
+from zope.app.principalannotation import PrincipalAnnotationUtility
+from zope.app.principalannotation import AnnotationsForPrincipal
 from zope.app.security.interfaces import IPrincipal
+from zope.app.site.tests.placefulsetup import PlacefulSetup
 from zope.app.tests import setup
-from zope.interface import implements
-from zope.app import zapi
+from zope.app.tests import ztapi
+from zope.app.utility.utility import LocalUtilityService
+from interfaces import IPrincipalAnnotationUtility
 
 class Principal(object):
 
@@ -41,48 +43,42 @@
         PlacefulSetup.setUp(self)
         sm = self.buildFolders(site='/')
 
-        root_sm = zapi.getGlobalServices()
+        self.util = PrincipalAnnotationUtility()
+        capi.provideUtility(self.util, IPrincipalAnnotationUtility)
 
-        svc = PrincipalAnnotationService()
-
-        root_sm.defineService("PrincipalAnnotation",
-                              IPrincipalAnnotationService)
-        root_sm.provideService("PrincipalAnnotation", svc)
-
-        self.svc = setup.addService(sm, 'PrincipalAnnotation', svc)
-
     def testGetSimple(self):
         prince = Principal('somebody')
-        self.assert_(not self.svc.hasAnnotations(prince))
+        self.assert_(not self.util.hasAnnotations(prince))
 
-        princeAnnotation = self.svc.getAnnotations(prince)
+        princeAnnotation = self.util.getAnnotations(prince)
         # Just getting doesn't actualy store. We don't want to store unless
         # we make a change.
-        self.assert_(not self.svc.hasAnnotations(prince))
+        self.assert_(not self.util.hasAnnotations(prince))
 
         princeAnnotation['something'] = 'whatever'
 
         # But now we should have the annotation:
-        self.assert_(self.svc.hasAnnotations(prince))
+        self.assert_(self.util.hasAnnotations(prince))
 
     def testGetFromLayered(self):
         princeSomebody = Principal('somebody')
         sm1 = self.makeSite('folder1')
-        subService = setup.addService(sm1, 'PrincipalAnnotation',
-                                      PrincipalAnnotationService())
+        setup.addService(sm1, 'Utilities', LocalUtilityService())
+        subUtil = setup.addUtility(sm1, '', IPrincipalAnnotationUtility,
+                                   PrincipalAnnotationUtility())
 
-        parentAnnotation = self.svc.getAnnotations(princeSomebody)
+        parentAnnotation = self.util.getAnnotations(princeSomebody)
 
         # Just getting doesn't actualy store. We don't want to store unless
         # we make a change.
-        self.assert_(not subService.hasAnnotations(princeSomebody))
+        self.assert_(not subUtil.hasAnnotations(princeSomebody))
 
         parentAnnotation['hair_color'] = 'blue'
 
         # But now we should have the annotation:
-        self.assert_(self.svc.hasAnnotations(princeSomebody))
+        self.assert_(self.util.hasAnnotations(princeSomebody))
 
-        subAnnotation = subService.getAnnotations(princeSomebody)
+        subAnnotation = subUtil.getAnnotations(princeSomebody)
         self.assertEquals(subAnnotation['hair_color'], 'blue')
 
         subAnnotation['foo'] = 'bar'
@@ -93,7 +89,7 @@
     def testAdapter(self):
         p = Principal('somebody')
         ztapi.provideAdapter(IPrincipal, IAnnotations,
-                             AnnotationsForPrincipal(self.svc))
+                             AnnotationsForPrincipal(self.util))
         annotations = IAnnotations(p)
         annotations["test"] = "bar"
         annotations = IAnnotations(p)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/publication/tests/test_zopepublication.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/publication/tests/test_zopepublication.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/publication/tests/test_zopepublication.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -61,7 +61,7 @@
 class UnauthenticatedPrincipal(Principal):
     implements(IUnauthenticatedPrincipal)
 
-class AuthService1(object):
+class AuthUtility1(object):
 
     def authenticate(self, request):
         return None
@@ -75,7 +75,7 @@
     def getPrincipal(self, id):
         return UnauthenticatedPrincipal(id)
 
-class AuthService2(AuthService1):
+class AuthUtility2(AuthUtility1):
 
     def authenticate(self, request):
         return Principal('test.bob')
@@ -92,15 +92,24 @@
     def raising(self, info, request=None):
         self.exceptions.append([info, request])
 
+
+class UtilityService(object):
+
+    utility = None
+
+    def getUtility(self, interface, name=''):
+        return self.utility
+
+
 class ServiceManager(object):
     implements(IServiceService) # a dirty lie
 
-    def __init__(self, auth):
-        self.auth = auth
+    def __init__(self, utils):
+        self.utils = utils
 
     def getService(self, name):
-        if name == Authentication:
-            return self.auth
+        if name == 'Utilities':
+            return self.utils
         raise ComponentLookupError(name)
 
 class LocatableObject(Location):
@@ -408,9 +417,13 @@
         app['f1'] = Folder()
         f1 = app['f1']
         f1['f2'] = Folder()
-        f1.setSiteManager(ServiceManager(AuthService1()))
+        utilservice1 = UtilityService()
+        utilservice1.utility = AuthUtility1()
+        f1.setSiteManager(ServiceManager(utilservice1))
         f2 = f1['f2']
-        f2.setSiteManager(ServiceManager(AuthService2()))
+        utilservice2 = UtilityService()
+        utilservice2.utility = AuthUtility2()
+        f2.setSiteManager(ServiceManager(utilservice2))
         get_transaction().commit()
 
         from zope.app.container.interfaces import ISimpleReadContainer

Modified: Zope3/branches/srichter-blow-services/src/zope/app/publication/zopepublication.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/publication/zopepublication.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/publication/zopepublication.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -48,6 +48,7 @@
 from zope.app.publication.publicationtraverse import PublicationTraverse
 from zope.app.security.principalregistry import principalRegistry as prin_reg
 from zope.app.security.interfaces import IUnauthenticatedPrincipal
+from zope.app.security.interfaces import IAuthenticationUtility
 from zope.app.site.interfaces import ISite
 from zope.app.traversing.interfaces import IPhysicallyLocatable
 
@@ -95,15 +96,16 @@
         sm = removeSecurityProxy(ob).getSiteManager()
 
         try:
-            auth_service = sm.getService(zapi.servicenames.Authentication)
+            utils = sm.getService(zapi.servicenames.Utilities)
+            auth = utils.getUtility(IAuthenticationUtility)
         except ComponentLookupError:
-            # No auth service here
+            # No auth utility here
             return
 
         # Try to authenticate against the auth service
-        principal = auth_service.authenticate(request)
+        principal = auth.authenticate(request)
         if principal is None:
-            principal = auth_service.unauthenticatedPrincipal()
+            principal = auth.unauthenticatedPrincipal()
             if principal is None:
                 # nothing to do here
                 return

Modified: Zope3/branches/srichter-blow-services/src/zope/app/registration/README.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/registration/README.txt	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/registration/README.txt	2004-12-21 16:57:29 UTC (rev 28670)
@@ -113,7 +113,7 @@
   This is a little but confusing, so we'll look at an example.
   Utilities are registered using 2 parameterer, the interface provided
   by the uttility, and the utility name.  For a given interface and
-  name, the utility service may have multiple ustility
+  name, the utility service may have multiple utility
   registrations. It uses a registration stack to store these. We can
   get the registration stack by calling `queryRegistrationsFor()` with
   a registration object that has the desired interface and name.  The

Modified: Zope3/branches/srichter-blow-services/src/zope/app/registration/interfaces.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/registration/interfaces.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/registration/interfaces.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -362,10 +362,10 @@
     """
 
     def getRegistrationManager():
-        """get a registration manager.
+        """Get a registration manager.
 
         Find a registration manager.  Clients can get the
-        registration manager without knowing it's name. Normally,
+        registration manager without knowing its name. Normally,
         folders have one registration manager. If there is more than
         one, this method will return one; which one is undefined.
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/adapter.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/adapter.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/adapter.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -24,7 +24,7 @@
     """Adapt an adapter factory to to provide trusted adapters
 
        Trusted adapters always adapt unproxied objects.  If asked to
-       adapt any proxid objects, it will unproxy them and then proxy the
+       adapt any proxied objects, it will unproxy them and then proxy the
        resulting adapter.
 
        Suppose we have an adapter factory:

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/basicauthadapter.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/basicauthadapter.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/basicauthadapter.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -18,8 +18,9 @@
 from zope.publisher.interfaces.http import IHTTPCredentials
 from loginpassword import LoginPassword
 
+
 class BasicAuthAdapter(LoginPassword):
-    """Adapter for handling HTTP Basic Auth.""" 
+    """Adapter for handling HTTP Basic Auth."""
 
     __used_for__ = IHTTPCredentials
 

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	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/browser/auth.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -18,7 +18,7 @@
 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 IAuthenticationService
+from zope.app.security.interfaces import IAuthenticationUtility
 from zope.app.security.principalregistry import UnauthenticatedPrincipal
 from zope.app.pagetemplate import ViewPageTemplateFile
 from zope.proxy import removeAllProxies
@@ -27,8 +27,8 @@
 
 search_label = _('search-button', 'Search')
 
-class AuthServiceSearchView(object):
-    __used_for__ = IAuthenticationService
+class AuthUtilitySearchView(object):
+    __used_for__ = IAuthenticationUtility
 
     def __init__(self, context, request):
         self.context = context

Deleted: Zope3/branches/srichter-blow-services/src/zope/app/security/browser/authservicesearchview.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/browser/authservicesearchview.txt	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/browser/authservicesearchview.txt	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1,62 +0,0 @@
-The Query View for Authentication Services
-==========================================
-
-A regular authentication service will not provide the `ISourceQueriables`
-interface, but it is a queriable itself, since it provides the simple
-`getPrincipals(name)` method:
-
-  >>> class Principal:
-  ...     def __init__(self, id): 
-  ...         self.id = id
-
-  >>> class MyAuthService:
-  ...     data = {'jim': Principal(42), 'don': Principal(0), 
-  ...             'stephan': Principal(1)}
-  ...
-  ...     def getPrincipals(self, name):
-  ...         return [principal
-  ...                 for id, principal in self.data.items()
-  ...                 if name in id]
-
-Now that we have our queriable, we create the view for it:
-
-  >>> from zope.app.security.browser.auth import AuthServiceSearchView
-  >>> from zope.publisher.browser import TestRequest
-  >>> request = TestRequest()
-  >>> view = AuthServiceSearchView(MyAuthService(), request)
-
-This allows us to render a search form.
-
-  >>> print view.render('test') # doctest: +NORMALIZE_WHITESPACE
-  <div class="row">
-  <div class="label">
-  Search String
-  </div>
-  <div class="field">
-  <input type="text" name="test.searchstring" />
-  </div>
-  </div>
-  <br /><input type="submit" name="test.search" value="Search" />
-
-If we ask for results:
-
-  >>> view.results('test')
-
-We don't get any, since we did not provide any. But if we give input:
-
-  >>> request.form['test.searchstring'] = 'n'
-
-we still don't get any:
-
-  >>> view.results('test')
-
-because we did not press the button. So let's press the button:
-
-  >>> request.form['test.search'] = 'Search'
-
-so that we now get results (!):
-
-  >>> ids = list(view.results('test'))
-  >>> ids.sort()
-  >>> ids
-  [0, 1]
\ No newline at end of file

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

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	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/browser/configure.zcml	2004-12-21 16:57:29 UTC (rev 28670)
@@ -3,10 +3,10 @@
    xmlns:browser="http://namespaces.zope.org/browser">
 
   <adapter
-      for="zope.app.security.interfaces.IAuthenticationService
+      for="zope.app.security.interfaces.IAuthenticationUtility
            zope.publisher.interfaces.browser.IBrowserRequest"
       provides="zope.app.form.browser.interfaces.ISourceQueryView"
-      factory="zope.app.security.browser.auth.AuthServiceSearchView" 
+      factory="zope.app.security.browser.auth.AuthUtilitySearchView" 
       />
 
   <adapter
@@ -51,7 +51,7 @@
 
  <browser:addMenuItem
      title="Permission"
-     description="A Secutiry Permission"
+     description="A Security Permission"
      class="..permission.LocalPermission"
      permission="zope.ManageServices"
      view="AddPermission.html"

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/browser/principalterms.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/browser/principalterms.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/browser/principalterms.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -42,7 +42,7 @@
         if principal_id not in self.context:
             raise LookupError, principal_id
 
-        auth = zapi.getService(zapi.servicenames.Authentication)
+        auth = zapi.principals()
         principal = auth.getPrincipal(principal_id)
 
         if principal is None:

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/browser/principalterms.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/browser/principalterms.txt	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/browser/principalterms.txt	2004-12-21 16:57:29 UTC (rev 28670)
@@ -3,18 +3,18 @@
 
 Principal Terms are used to support browser interfaces for searching principal
 sources. They provide access to tokens and titles for values. The principal
-terms view uses an authentication service to get principal titles. Let's
-create an authentication service to demonstrate how this works:
+terms view uses an authentication utility to get principal titles. Let's
+create an authentication utility to demonstrate how this works:
 
   >>> class Principal:
   ...     def __init__(self, id, title):
   ...         self.id, self.title = id, title
 
   >>> from zope.interface import implements
-  >>> from zope.app.security.interfaces import IAuthenticationService
+  >>> from zope.app.security.interfaces import IAuthenticationUtility
   >>> from zope.app.security.interfaces import PrincipalLookupError
-  >>> class AuthService:
-  ...     implements(IAuthenticationService)
+  >>> class AuthUtility:
+  ...     implements(IAuthenticationUtility)
   ...     data = {'jim': 'Jim Fulton', 'stephan': 'Stephan Richter'}
   ...
   ...     def getPrincipal(self, id):
@@ -23,18 +23,17 @@
   ...             return Principal(id, title)
   ...         raise PrincipalLookupError
 
-Now we need to install the authentication service:
+Now we need to install the authentication utility:
 
   >>> from zope.app.tests import ztapi
-  >>> ztapi.provideService('Authentication', AuthService(), 
-  ...                      IAuthenticationService)
+  >>> ztapi.provideUtility(IAuthenticationUtility, AuthUtility())
 
 We need a principal source so that we can create a view from it.
 
   >>> from zope.app import zapi
   >>> class PrincipalSource:
   ...     def __contains__(self, id):
-  ...          auth = zapi.getService('Authentication')
+  ...          auth = zapi.getUtility(IAuthenticationUtility)
   ...          try:
   ...              auth.getPrincipal(id)
   ...          except PrincipalLookupError:

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	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/browser/tests.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -22,7 +22,7 @@
 
 def test_suite():
     return unittest.TestSuite((
-        doctest.DocFileSuite('authservicesearchview.txt',
+        doctest.DocFileSuite('authutilitysearchview.txt',
                              setUp=placelesssetup.setUp,
                              tearDown=placelesssetup.tearDown),
         doctest.DocFileSuite('principalterms.txt',

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/configure.zcml
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/configure.zcml	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/configure.zcml	2004-12-21 16:57:29 UTC (rev 28670)
@@ -22,12 +22,8 @@
   <include file="globalmodules.zcml" />
   <include file="_protections.zcml" />
 
-  <serviceType
-      id="Authentication" 
-      interface=".interfaces.IAuthenticationService" />
-
-  <service
-      serviceType="Authentication" 
+  <utility
+      provides=".interfaces.IAuthenticationUtility" 
       component=".principalregistry.principalRegistry" />
 
   <localUtility class=".permission.LocalPermission">

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/interfaces.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/interfaces.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/interfaces.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -33,23 +33,22 @@
     Authenticated principals are preferable to UnauthenticatedPrincipals.
     """
 
-class IAuthenticationService(Interface):
+class IAuthenticationUtility(Interface):
     """Provide support for establishing principals for requests.
 
-    This is implemented by performing protocol-specific actions,
-    such as issuing challenges or providing login interfaces.
+    This is implemented by performing protocol-specific actions, such as
+    issuing challenges or providing login interfaces.
 
-    IAuthenticationService objects are used to implement
-    authentication services. Because they implement services, they are
-    expected to collaborate with services in other contexts. Client
-    code doesn't search a context and call multiple services. Instead,
-    client code will call the most specific service in a place and
-    rely on the service to delegate to other services as necessary.
+    `IAuthenticationUtility` objects are used to implement authentication
+    utilities. Because they implement services, they are expected to
+    collaborate with services in other contexts. Client code doesn't search a
+    context and call multiple services. Instead, client code will call the
+    most specific service in a place and rely on the service to delegate to
+    other services as necessary.
 
-    The interface doesn't include methods for data
-    management. Services may use external data and not allow
-    management in Zope. Simularly, the data to be managed may vary
-    with different implementations of a service.
+    The interface doesn't include methods for data management. Services may
+    use external data and not allow management in Zope. Simularly, the data to
+    be managed may vary with different implementations of a service.
     """
 
     def authenticate(request):
@@ -127,10 +126,15 @@
         similar to (e.g. contain) the given name.
         """
 
+############################################################################
+# BBB: 12/15/2004
+IAuthenticationService = IAuthenticationUtility
+############################################################################
+
 class ILoginPassword(Interface):
     """A password based login.
 
-    An IAuthenticationService would use this (adapting a request),
+    An `IAuthenticationUtility` would use this (adapting a request),
     to discover the login/password passed from the user, or to
     indicate that a login is required.
     """

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/principal.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/principal.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/principal.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -15,9 +15,9 @@
 
 $Id$
 """
+from zope.app import zapi
 from zope.app.security.interfaces import PrincipalLookupError
-from zope.app import zapi
-from zope.app.servicenames import Authentication
+from zope.app.security.interfaces import IAuthenticationUtility
 
 # BBB Backward Compatibility
 from zope.exceptions import NotFoundError
@@ -25,7 +25,7 @@
 
 def checkPrincipal(context, principal_id):
 
-    auth = zapi.getService(Authentication, context)
+    auth = zapi.getUtility(IAuthenticationUtility, context=context)
     try:
         if auth.getPrincipal(principal_id):
             return

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/principalregistry.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/principalregistry.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/principalregistry.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -11,7 +11,7 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Global Authentication Service or Principal Registry
+"""Global Authentication Utility or Principal Registry
 
 $Id$
 """
@@ -20,7 +20,7 @@
 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 IAuthenticationService, IPrincipal
+from zope.app.security.interfaces import IAuthenticationUtility, IPrincipal
 from zope.app.security.interfaces import IUnauthenticatedPrincipal
 from zope.app.container.contained import Contained, contained
 from warnings import warn
@@ -30,9 +30,9 @@
 
 class PrincipalRegistry(object):
 
-    implements(IAuthenticationService)
+    implements(IAuthenticationUtility)
 
-    # Methods implementing IAuthenticationService
+    # Methods implementing IAuthenticationUtility
 
     def authenticate(self, request):
         a = ILoginPassword(request, None)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/tests/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/tests/__init__.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/tests/__init__.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -22,8 +22,6 @@
 def addCheckerPublic():
     """Add the CheckerPublic permission as 'zope.Public'"""
 
-    utilityService = zapi.getGlobalService(zapi.servicenames.Utilities)
-
     perm = Permission('zope.Public', 'Public',
             """Special permission used for resources that are always public
 
@@ -31,4 +29,5 @@
             it allows security computation to be bypassed.
             """
             )
-    utilityService.provideUtility(IPermission, perm, perm.id)
+    gsm = zapi.getGlobalSiteManager()
+    gsm.provideUtility(IPermission, perm, perm.id)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/tests/test_securitydirectives.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/tests/test_securitydirectives.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/tests/test_securitydirectives.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -24,7 +24,7 @@
 from zope.app.tests.placelesssetup import PlacelessSetup
 
 from zope.app.servicenames import Authentication
-from zope.app.security.interfaces import IAuthenticationService, IPermission
+from zope.app.security.interfaces import IAuthenticationUtility, IPermission
 from zope.app.security.principalregistry import principalRegistry
 from zope.app.security.settings import Allow
 import zope.app.security.tests
@@ -34,12 +34,9 @@
 
     def setUp(self):
         super(TestBase, self).setUp()
-        services = zapi.getGlobalServices()
+        ztapi.provideUtility(IAuthenticationUtility, principalRegistry)
 
-        services.defineService(Authentication, IAuthenticationService)
-        services.provideService(Authentication, principalRegistry)
 
-
 class TestPrincipalDirective(TestBase, unittest.TestCase):
 
     def testRegister(self):

Modified: Zope3/branches/srichter-blow-services/src/zope/app/security/vocabulary.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/security/vocabulary.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/security/vocabulary.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -22,9 +22,9 @@
 from zope.interface import implements
 from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
 from zope.schema.interfaces import ISourceQueriables
-from zope.app.security.interfaces import IPermission
+from zope.app.security.interfaces import IPermission, IAuthenticationUtility
 from zope.app.security.interfaces import PrincipalLookupError
-from zope.app.component.localservice import queryNextService
+from zope.app.utility.utility import queryNextUtility
 
 # BBB Backward Compatibility
 from zope.exceptions import NotFoundError
@@ -115,25 +115,25 @@
 
         We want to check whether the system knows about a particular
         principal, which is referenced via its id. The source will go through
-        the most local authentication service to look for the
-        principal. Whether the service consults other services to give an
-        answer is up to the service itself.
+        the most local authentication utility to look for the
+        principal. Whether the utility consults other utilities to give an
+        answer is up to the utility itself.
 
         First we need to create a dummy service that will return a user, if
         the id is 'bob'.
         
-        >>> class DummyService:
+        >>> class DummyUtility:
         ...     def getPrincipal(self, id):
         ...         if id == 'bob':
         ...             return id
         ...         raise PrincipalLookupError(id)
 
         Since we do not want to bring up the entire component architecture, we
-        simply monkey patch the `getService()` method to always return our
-        dummy authentication service.
+        simply monkey patch the `getUtility()` method to always return our
+        dummy authentication utility.
 
-        >>> temp = zapi.getService
-        >>> zapi.getService = lambda name: DummyService()
+        >>> temp = zapi.getUtility
+        >>> zapi.getUtility = lambda iface: DummyUtility()
 
         Now initialize the principal source and test the method
 
@@ -145,9 +145,9 @@
 
         Now revert our patch.
 
-        >>> zapi.getService = temp
+        >>> zapi.getUtility = temp
         """
-        auth = zapi.getService(zapi.servicenames.Authentication)
+        auth = zapi.getUtility(IAuthenticationUtility)
         try:
             auth.getPrincipal(id)
         except PrincipalLookupError:
@@ -157,7 +157,7 @@
                 "A %s instance raised a NotFoundError in "
                 "getPrincipals.  Raising NotFoundError in this "
                 "method is deprecated and will no-longer be supported "
-                "staring in ZopeX3 3.3.  PrincipalLookupError should "
+                "starting in ZopeX3 3.3.  PrincipalLookupError should "
                 "be raised instead."
                 % auth.__class__.__name__,
                 DeprecationWarning)
@@ -171,40 +171,42 @@
         Queriables are responsible for providing interfaces to search for
         principals by a set of given parameters (can be different for the
         various queriables). This method will walk up through all of the
-        authentication services to look for queriables.
+        authentication utilities to look for queriables.
 
-        >>> class DummyService1:
+        >>> class DummyUtility1:
+        ...     implements(IAuthenticationUtility)
         ...     __parent__ = None
         ...     def __repr__(self): return 'dummy1'
-        >>> dummy1 = DummyService1()
+        >>> dummy1 = DummyUtility1()
         
-        >>> class DummyService2:
-        ...     implements(ISourceQueriables)
+        >>> class DummyUtility2:
+        ...     implements(ISourceQueriables, IAuthenticationUtility)
         ...     __parent__ = None
         ...     def getQueriables(self):
         ...         return ('1', 1), ('2', 2), ('3', 3)
-        >>> dummy2 = DummyService2()
+        >>> dummy2 = DummyUtility2()
 
-        >>> class DummyService3(DummyService2):
+        >>> class DummyUtility3(DummyUtility2):
+        ...     implements(IAuthenticationUtility)
         ...     def getQueriables(self):
         ...         return ('4', 4),
-        >>> dummy3 = DummyService3()
+        >>> dummy3 = DummyUtility3()
 
-        >>> from zope.app.component.localservice import testingNextService
-        >>> testingNextService(dummy1, dummy2, 'Authentication')
-        >>> testingNextService(dummy2, dummy3, 'Authentication')
+        >>> from zope.app.utility.utility import testingNextUtility
+        >>> testingNextUtility(dummy1, dummy2, IAuthenticationUtility)
+        >>> testingNextUtility(dummy2, dummy3, IAuthenticationUtility)
         
-        >>> temp = zapi.getService
-        >>> zapi.getService = lambda name: dummy1
+        >>> temp = zapi.getUtility
+        >>> zapi.getUtility = lambda iface: dummy1
 
         >>> source = PrincipalSource()
         >>> list(source.getQueriables())
         [(u'0', dummy1), (u'1.1', 1), (u'1.2', 2), (u'1.3', 3), (u'2.4', 4)]
 
-        >>> zapi.getService = temp
+        >>> zapi.getUtility = temp
         """
         i = 0
-        auth = zapi.getService(zapi.servicenames.Authentication)
+        auth = zapi.getUtility(IAuthenticationUtility)
         while True:
             queriables = ISourceQueriables(auth, None)
             if queriables is None:
@@ -212,7 +214,7 @@
             else:
                 for qid, queriable in queriables.getQueriables():
                     yield unicode(i)+'.'+unicode(qid), queriable
-            auth = queryNextService(auth, zapi.servicenames.Authentication)
+            auth = queryNextUtility(auth, IAuthenticationUtility)
             if auth is None:
                 break
             i += 1

Modified: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/browser/granting.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/browser/granting.txt	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/browser/granting.txt	2004-12-21 16:57:29 UTC (rev 28670)
@@ -25,16 +25,16 @@
     >>> ztapi.provideUtility(IPermission, Permission(u'permission3', 
     ...                      u'Permission 3'), u'permission3')
 
-  - Authentication Service
+  - Authentication Utility
 
     >>> class Principal:
     ...     def __init__(self, id, title): self.id, self.title = id, title
 
-    >>> from zope.app.security.interfaces import IAuthenticationService
+    >>> from zope.app.security.interfaces import IAuthenticationUtility
     >>> from zope.app.security.interfaces import PrincipalLookupError
     >>> from zope.interface import implements
-    >>> class AuthService:
-    ...     implements(IAuthenticationService)
+    >>> class AuthUtility:
+    ...     implements(IAuthenticationUtility)
     ...     data = {'jim': Principal('jim', 'Jim Fulton'),
     ...             'stephan': Principal('stephan', 'Stephan Richter')}
     ...
@@ -49,8 +49,7 @@
     ...                 for principal in self.data.values()
     ...                 if search in principal.title]
 
-    >>> ztapi.provideService('Authentication', AuthService(), 
-    ...                      IAuthenticationService)
+    >>> ztapi.provideUtility(IAuthenticationUtility, AuthUtility())
 
   - Security-related Adapters
 
@@ -91,10 +90,10 @@
     >>> from zope.app.form.browser.interfaces import ITerms
     >>> ztapi.browserViewProviding(IPrincipalSource, PrincipalTerms, ITerms)
 
-    >>> from zope.app.security.browser.auth import AuthServiceSearchView
+    >>> from zope.app.security.browser.auth import AuthUtilitySearchView
     >>> from zope.app.form.browser.interfaces import ISourceQueryView
-    >>> ztapi.browserViewProviding(IAuthenticationService, 
-    ...                            AuthServiceSearchView,
+    >>> ztapi.browserViewProviding(IAuthenticationUtility, 
+    ...                            AuthUtilitySearchView,
     ...                            ISourceQueryView)
 
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_principalpermissionmanager.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_principalpermissionmanager.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_principalpermissionmanager.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -21,7 +21,8 @@
 from zope.app.tests import ztapi
 from zope.app.tests.placelesssetup import PlacelessSetup
 
-from zope.app.security.interfaces import IAuthenticationService, IPermission
+from zope.app.security.interfaces import IPermission
+from zope.app.security.interfaces import IAuthenticationUtility
 from zope.app.security.permission import Permission
 
 from zope.app.servicenames import Authentication
@@ -41,12 +42,9 @@
 
     def setUp(self):
         super(Test, self).setUp()
-        services = zapi.getGlobalServices()
+        ztapi.provideUtility(IAuthenticationUtility, principalRegistry)
 
-        services.defineService(Authentication, IAuthenticationService)
-        services.provideService(Authentication, principalRegistry)
 
-
     def _make_principal(self, id=None, title=None):
         p = principalRegistry.definePrincipal(
             id or 'APrincipal',

Modified: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_principalrolemanager.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_principalrolemanager.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_principalrolemanager.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -20,9 +20,8 @@
 from zope.app import zapi
 from zope.app.tests import ztapi
 from zope.app.tests.placelesssetup import PlacelessSetup
-from zope.app.servicenames import Authentication
 
-from zope.app.security.interfaces import IAuthenticationService
+from zope.app.security.interfaces import IAuthenticationUtility
 from zope.app.security.settings import Allow, Deny
 from zope.app.security.principalregistry import principalRegistry
 
@@ -39,11 +38,8 @@
 
     def setUp(self):
         super(Test, self).setUp()
-        services = zapi.getGlobalServices()
+        ztapi.provideUtility(IAuthenticationUtility, principalRegistry)
 
-        services.defineService(Authentication, IAuthenticationService)
-        services.provideService(Authentication, principalRegistry)
-
     def _make_principal(self, id=None, title=None):
         p = principalRegistry.definePrincipal(
             id or 'APrincipal',

Modified: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_securitydirectives.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_securitydirectives.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_securitydirectives.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -17,16 +17,16 @@
 """
 import unittest
 
+from zope.configuration import xmlconfig
+from zope.configuration.config import ConfigurationConflictError
+
 from zope.app import zapi
 from zope.app.tests import ztapi
-from zope.app.servicenames import Authentication
-from zope.app.security.interfaces import IAuthenticationService
 
-from zope.configuration.config import ConfigurationConflictError
-from zope.configuration import xmlconfig
 from zope.app.tests.placelesssetup import PlacelessSetup
 
 from zope.app.security.interfaces import IPermission
+from zope.app.security.interfaces import IAuthenticationUtility
 from zope.app.security.permission import Permission
 from zope.app.security.settings import Allow
 from zope.app.security.principalregistry import principalRegistry
@@ -52,12 +52,9 @@
 
     def setUp(self):
         super(TestBase, self).setUp()
-        services = zapi.getGlobalServices()
+        ztapi.provideUtility(IAuthenticationUtility, principalRegistry)
 
-        services.defineService(Authentication, IAuthenticationService)
-        services.provideService(Authentication, principalRegistry)
 
-
 class TestRoleDirective(TestBase, unittest.TestCase):
 
     def testRegister(self):

Modified: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_zopepolicy.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_zopepolicy.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/tests/test_zopepolicy.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -24,7 +24,6 @@
 from zope.app.annotation.interfaces import IAttributeAnnotatable
 from zope.app.annotation.interfaces import IAnnotations
 from zope.app.annotation.attribute import AttributeAnnotations
-from zope.app.security.interfaces import IAuthenticationService
 from zope.app.securitypolicy.interfaces import IGrantInfo
 from zope.app.securitypolicy.interfaces import IPrincipalRoleManager
 from zope.app.securitypolicy.interfaces import IPrincipalPermissionManager
@@ -57,8 +56,6 @@
     ztapi.provideAdapter(
         IAnnotatable, IGrantInfo,
         AnnotationGrantInfo)
-    zapi.getGlobalServices().defineService('Authentication',
-                                           IAuthenticationService)
 
 
 def test_suite():

Modified: Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/zopepolicy.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/zopepolicy.txt	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/securitypolicy/zopepolicy.txt	2004-12-21 16:57:29 UTC (rev 28670)
@@ -9,7 +9,7 @@
 
   - roles to principals,
 
-  - permissions to principals, and 
+  - permissions to principals, and
 
   - permissions to roles
 
@@ -33,7 +33,7 @@
   ...         self.groups = []
 
   >>> principal = Principal('bob')
- 
+
 Roles and permissions are also represented by objects, however, for
 the purposes of the scurity policy, only string `ids` are used.
 
@@ -169,7 +169,7 @@
 global grants:
 
   >>> from zope.app.securitypolicy.rolepermission \
-  ...     import rolePermissionManager as roleperG  
+  ...     import rolePermissionManager as roleperG
   >>> from zope.app.securitypolicy.principalpermission \
   ...     import principalPermissionManager as prinperG
   >>> from zope.app.securitypolicy.principalrole \
@@ -207,7 +207,7 @@
   >>> interaction.checkPermission('P3G', ob)
   True
 
-Local verses global grants
+Local versus global grants
 --------------------------
 
 We, of course, acquire global grants by default:
@@ -225,7 +225,7 @@
   >>> prinrole.assignRoleToPrincipal('R1G', 'bob')
   >>> interaction.checkPermission('P1G', ob)
   False
-  
+
 And local role-based denials don't override global
 principal-grants:
 
@@ -267,7 +267,7 @@
 ------------
 
 We can have sub-locations. A sublocation of a location is an object
-whos `__parent__` attribute is the location:
+whose `__parent__` attribute is the location:
 
   >>> ob2 = Ob()
   >>> ob2.__parent__ = ob
@@ -290,7 +290,7 @@
   True
 
 Sublocation role-based grants do not override their parent
-prinicipal-specific denials:
+principal-specific denials:
 
   >>> roleper2  = interfaces.IRolePermissionManager(ob2)
   >>> prinrole2 = interfaces.IPrincipalRoleManager(ob2)
@@ -300,7 +300,7 @@
   >>> prinrole2.assignRoleToPrincipal('R1', 'bob')
   >>> interaction.checkPermission('P1', ob2)
   False
-  
+
 And local role-based denials don't override their parents
 principal-grant:
 
@@ -326,8 +326,8 @@
   >>> prinrole.removeRoleFromPrincipal('R1', 'bob')
   >>> interaction.checkPermission('P4', ob2)
   True
-  
 
+
 Of course, a local permission-based grant or denial overrides any
 global setting and overrides local role-based grants or denials:
 
@@ -340,7 +340,7 @@
   False
 
 If an object is not annotatable, but does have a parent, it will get
-it's grants from it's parent:
+its grants from its parent:
 
   >>> class C:
   ...     pass
@@ -433,7 +433,7 @@
 ------------------
 
 The security policy defines a special role named "zope.Anonymous".  All
-principals have this role and the role cannot be taken away. 
+principals have this role and the role cannot be taken away.
 
   >>> roleperG.grantPermissionToRole('P5', 'zope.Anonymous', False)
   >>> interaction.checkPermission('P5', ob2)
@@ -496,22 +496,23 @@
 For our examples here, we'll create and register a stub principal
 authentication service:
 
-  >>> from zope.app.security.interfaces import IAuthenticationService
+  >>> from zope.app.security.interfaces import IAuthenticationUtility
   >>> class FauxPrincipals(dict):
-  ...     zope.interface.implements(IAuthenticationService)
+  ...     zope.interface.implements(IAuthenticationUtility)
   ...     def getPrincipal(self, id):
   ...         return self[id]
 
   >>> auth = FauxPrincipals()
 
   >>> from zope.app.tests import ztapi
-  >>> ztapi.provideService('Authentication', auth)
+  >>> ztapi.provideUtility(IAuthenticationUtility, auth)
+  >>> from zope.app import zapi
 
 Let's define a group:
 
   >>> auth['g1'] = Principal('g1')
 
-Lets put the principal in our group.  We do that by adding the group id
+Let's put the principal in our group.  We do that by adding the group id
 to the new principals groups:
 
   >>> principal.groups.append('g1')
@@ -594,8 +595,8 @@
   >>> interaction.checkPermission('gP2', ob2)
   True
 
-In a case where a principal has two or more groups, the group denys
-prevent allows from thier parents. They don't prevent the principal
+In a case where a principal has two or more groups, the group denies
+prevent allows from their parents. They don't prevent the principal
 from getting an allow from another principal.
 
 Grants can be inherited from ancestor groups through multiple paths.
@@ -608,7 +609,7 @@
 
   >>> interaction.checkPermission('gP3', ob2)
   False
-  
+
 Let's make g2 a group of g3:
 
   >>> auth['g3'].groups.append('g2')
@@ -641,7 +642,7 @@
   >>> prinrole.assignRoleToPrincipal('gR1', 'bob')
   >>> interaction.checkPermission('gP4', ob2)
   True
-  
+
 Cleanup
 -------
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/session/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/session/tests.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/session/tests.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -17,7 +17,7 @@
 """
 import unittest, doctest, os, os.path, sys
 from zope.app import zapi
-from zope.app.tests import ztapi, placelesssetup
+from zope.app.testing import ztapi, placelesssetup
 
 from zope.app.session.interfaces import IClientId, IClientIdManager, ISession
 from zope.app.session.interfaces import ISessionDataContainer
@@ -97,5 +97,3 @@
 
 if __name__ == '__main__':
     unittest.main()
-
-# vim: set filetype=python ts=4 sw=4 et si

Modified: Zope3/branches/srichter-blow-services/src/zope/app/site/service.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/site/service.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/site/service.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -63,16 +63,11 @@
        zope.app.registration.interfaces.IRegisterableContainer)
 
 
-class SiteManager(
-    BTreeContainer,
-    PersistentModuleRegistry,
-    ):
+class SiteManager(BTreeContainer, PersistentModuleRegistry):
 
-    zope.interface.implements(
-        ISiteManager,
-        IRegisterableContainerContainer,
-        IRegistry,
-        )
+    zope.interface.implements(ISiteManager,
+                              IRegisterableContainerContainer,
+                              IRegistry)
 
     def __init__(self, site):
         self._bindings = {}
@@ -171,7 +166,7 @@
 
         # This is rather tricky. Normally, getting a service requires
         # the use of other services, like the adapter service.  We
-        # need to be careful not to get into an infinate recursion by
+        # need to be careful not to get into an infinite recursion by
         # getting out getService to be called while looking up
         # services, so we'll use _v_calling to prevent recursive
         # getService calls.
@@ -179,16 +174,15 @@
         if name == 'Services':
             return self # We are the service service
 
-        if not getattr(self, '_v_calling', 0):
+        if not getattr(self, '_v_calling', False):
 
-            self._v_calling = 1
+            self._v_calling = True
             try:
                 service = self.queryActiveComponent(name)
                 if service is not None:
                     return service
-
             finally:
-                self._v_calling = 0
+                self._v_calling = False
 
         return getNextService(self, name)
 
@@ -206,16 +200,15 @@
         if name == 'Services':
             return self # We are the service service
 
-        if not getattr(self, '_v_calling', 0):
+        if not getattr(self, '_v_calling', False):
 
-            self._v_calling = 1
+            self._v_calling = True
             try:
                 service = self.queryActiveComponent(name)
                 if service is not None:
                     return service
-
             finally:
-                self._v_calling = 0
+                self._v_calling = False
 
         return default
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/site/tests/placefulsetup.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/site/tests/placefulsetup.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/site/tests/placefulsetup.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -16,8 +16,8 @@
 $Id$
 """
 from zope.app import zapi
-from zope.app.tests import setup
-from zope.app.tests.placelesssetup import PlacelessSetup
+from zope.app.testing import setup
+from zope.app.testing.placelesssetup import PlacelessSetup
 from zope.app.folder import rootFolder
 
 class Place(object):

Modified: Zope3/branches/srichter-blow-services/src/zope/app/sqlscript/browser/sqlscript.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/sqlscript/browser/sqlscript.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/sqlscript/browser/sqlscript.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -127,7 +127,8 @@
             name = self.context.contentName
             container = self.context.context
             obj = container[name]
-            url = zapi.getView(obj, 'absolute_url', self.request)()
+            url = zapi.getMultiAdapter((obj, self.request),
+                                       name='absolute_url')()
             url = '%s/test.html' % url
             return url
         else:

Modified: Zope3/branches/srichter-blow-services/src/zope/app/tests/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/tests/__init__.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/tests/__init__.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1,2 +1,19 @@
 #
 # This file is necessary to make this directory a package.
+
+##############################################################################
+# BBB: backward-comptibility; 12/18/2004
+import sys
+from zope.app.testing import placelesssetup
+sys.modules['zope.app.tests.placelesssetup'] = placelesssetup
+from zope.app.testing import setup
+sys.modules['zope.app.tests.setup'] = setup
+from zope.app.testing import dochttp
+sys.modules['zope.app.tests.dochttp'] = dochttp
+from zope.app.testing import functional
+sys.modules['zope.app.tests.functional'] = functional
+from zope.app.testing import test
+sys.modules['zope.app.tests.test'] = test
+from zope.app.testing import ztapi
+sys.modules['zope.app.tests.ztapi'] = ztapi
+#############################################################################

Deleted: Zope3/branches/srichter-blow-services/src/zope/app/tests/dochttp.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/tests/dochttp.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/tests/dochttp.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1,224 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (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.
-#
-##############################################################################
-"""Convert an http tcpwatch session to a doctest
-
-$Id$
-"""
-
-import errno
-import optparse
-import os
-import re
-import rfc822
-import sys
-
-usage = """usage: %prog <options> directory
-
-Convert an http tcpwatch recorded sesssion to a doctest file, which is
-written to standard output.
-
-"""
-
-parser = optparse.OptionParser(usage)
-parser.add_option("-p", "--prefix", default="watch",
-                  help="Prefix for recorded tcpwatch session files")
-parser.add_option("-U", "--skip-url", action="append",
-                  help="Regular expression for URLs to skip")
-parser.add_option("-E", "--skip-extension", action="append",
-                  help="URL file-extension to skip")
-parser.add_option("-e", "--extension", action="append",
-                  help="URL file-extension to include")
-parser.add_option("-I", "--skip-request-header", action="append",
-                  help="Request header to skip")
-parser.add_option("-O", "--skip-response-header", action="append",
-                  help="Response header to skip")
-parser.add_option("-r", "--clean-redirects", action="store_true",
-                  help="Strip content from redirect responses",
-                  default=False)
-
-default_options = [
-    '-e', 'html',
-
-    '-I', 'Accept-Charset', '-I', 'Accept-Encoding', '-I', 'Accept-Language',
-    '-I', 'Accept', '-I', 'Connection', '-I', 'Host', '-I', 'Keep-Alive',
-    '-I', 'User-Agent',
-
-    '-O', 'Date', '-O', 'Server', '-O', 'X-Content-Type-Warning',
-    '-O', 'X-Powered-By',
-
-    ]
-
-def dochttp(args=sys.argv[1:], default=None):
-    """Convert a tcpwatch recorded sesssion to a doctest file"""
-    if default is None:
-        default = default_options
-
-    options, args = parser.parse_args(default+args)
-    try:
-        directory, = args
-    except:
-        parser.print_help()
-        sys.exit(1)
-
-    skip_extensions = options.skip_extension or ()
-    extensions = [ext for ext in (options.extension or ())
-                  if ext not in skip_extensions]
-    skip_urls = [re.compile(pattern) for pattern in (options.skip_url or ())]
-
-    names = [name[:-len(".request")]
-             for name in os.listdir(directory)
-             if name.startswith(options.prefix) and name.endswith('.request')
-             ]
-    names.sort()
-
-    extre = re.compile("[.](\w+)$")
-
-    for name in names:
-        requests =  Requests(
-                        open(os.path.join(directory, name + ".request"), 'rb'),
-                        options.skip_request_header,
-                        )
-        responses = Responses(
-                        open(os.path.join(directory, name + ".response"), 'rb'),
-                        options.skip_response_header,
-                        )
-
-        # We use map so as *not* to truncate at shortest input.
-        # We want an error if the number of requests and responses
-        # is different.
-        for request, response in map(None, requests, responses):
-            assert (request and response) or not (request or response)
-
-            path = request.path
-            ext = extre.search(path)
-            if ext:
-                ext = ext.group(1)
-                if extensions:
-                    if ext not in extensions:
-                        continue
-                else:
-                    if ext in skip_extensions:
-                        continue
-            
-            for skip_url in skip_urls:
-                if skip_url.search(request.path):
-                    break
-            else:
-                try:
-                    output_test(request, response, options.clean_redirects)
-                except IOError, e:
-                    if e.errno == errno.EPIPE:
-                        return
-                    raise
-    
-
-def output_test(request, response, clean_redirects=False):
-    print
-    print
-    print '  >>> print http(r"""'
-    print '  ...', '\n  ... '.join(request.lines())+'""")'
-    if response.code in (301, 302, 303) and clean_redirects:
-        if response.headers:
-            for i in range(len(response.headers)):
-                h, v = response.headers[i]
-                if h == "Content-Length":
-                    response.headers[i] = (h, "...")
-        lines = response.header_lines()
-        if lines:
-            lines.append("...")
-    else:
-        lines = response.lines()
-    print ' ', '\n  '.join([line.rstrip() and line or '<BLANKLINE>'
-                             for line in lines])
-
-class Message:
-
-    start = ''
-
-    def __init__(self, file, skip_headers):
-        start = file.readline().rstrip()
-        if start:
-            self.start = start
-            if start.startswith("HTTP/"):
-                # This is a response; extract the response code:
-                self.code = int(start.split()[1])
-            headers = [split_header(header)
-                       for header in rfc822.Message(file).headers
-                       ]
-            headers = [
-                ('-'.join([s.capitalize() for s in name.split('-')]),
-                 v.rstrip()
-                 )
-                for (name, v) in headers
-                if name.lower() not in skip_headers
-            ]
-            self.headers = headers
-            content_length = int(dict(headers).get('Content-Length', '0'))
-            if content_length:
-                self.body = file.read(content_length).split('\n')
-            else:
-                self.body = []
-
-    def __nonzero__(self):
-        return bool(self.start)
-
-    def lines(self):
-        output = self.header_lines()
-        if output:
-            output.extend(self.body)
-        return output
-
-    def header_lines(self):
-        if self.start:
-            output = [self.start]
-            headers = ["%s: %s" % (name, v) for (name, v) in self.headers]
-            headers.sort()
-            output.extend(headers)
-            output.append('')
-        else:
-            output = []
-        return output
-
-headerre = re.compile('(\S+): (.+)$')
-def split_header(header):
-    return headerre.match(header).group(1, 2)
-
-def messages(cls, file, skip_headers):
-    skip_headers = [name.lower() for name in (skip_headers or ())]
-    while 1:
-        message = cls(file, skip_headers)
-        if message:
-            yield message
-        else:
-            break
-        
-class Request(Message):
-
-    path = ''
-    
-    def __init__(self, file, skip_headers):
-        Message.__init__(self, file, skip_headers)
-        if self.start:
-            self.command, self.path, self.protocol = self.start.split()
-    
-def Requests(file, skip_headers):
-    return messages(Request, file, skip_headers)
-    
-def Responses(file, skip_headers):
-    return messages(Message, file, skip_headers)
-
-main = dochttp
-
-if __name__ == '__main__':
-    main()

Deleted: Zope3/branches/srichter-blow-services/src/zope/app/tests/dochttp.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/tests/dochttp.txt	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/tests/dochttp.txt	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1,31 +0,0 @@
-Steps to get started:
-
-0. Use a clean/missing Data.fs
-
-1. Create a manager with the name "mgr", password "mgrpw", and grant
-   the zope.Manager role.
-
-2. Install tcpwatch.
-
-3. Create a temporary directory to record tcpwatch output.
-
-4. Run tcpwatch using:
-   tcpwatch.py -L 8081:8080 -s -r tmpdir
-   (the ports are the listening port and forwarded-to port; the
-   second need to match the Zope configuration)
-
-5. In a browser, connect to the listening port and do whatever needs
-   to be recorded.
-
-6. Shut down tcpwatch.
-
-7. Run the script src/zope/app/tests/dochttp.py:
-   python2.3 src/zope/app/tests/dochttp.py tmpdir > somefile.txt
-
-8. Edit the generated text file to add explanations and elide
-   uninteresting portions of the output.
-
-9. In a functional test module (usually ftests.py), import
-   FunctionalDocFileSuite from zope.app.tests.functional and
-   instantiate it, passing the name of the text file containing the
-   test.

Deleted: Zope3/branches/srichter-blow-services/src/zope/app/tests/functional.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/tests/functional.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/tests/functional.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1,634 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 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 testing framework for Zope 3.
-
-There should be a file 'ftesting.zcml' in the current directory.
-
-$Id$
-"""
-import logging
-import re
-import rfc822
-import sys
-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.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.tests.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.zopepublication import ZopePublication
-from zope.app.publication.http import HTTPPublication
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.publisher.interfaces.browser import IDefaultSkin
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.app.component.hooks import setSite, getSite
-
-HTTPTaskStub = StringIO
-
-
-class ResponseWrapper(object):
-    """A wrapper that adds several introspective methods to a response."""
-
-    def __init__(self, response, outstream, path):
-        self._response = response
-        self._outstream = outstream
-        self._path = path
-
-    def getOutput(self):
-        """Returns the full HTTP output (headers + body)"""
-        return self._outstream.getvalue()
-
-    def getBody(self):
-        """Returns the response body"""
-        output = self._outstream.getvalue()
-        idx = output.find('\r\n\r\n')
-        if idx == -1:
-            return None
-        else:
-            return output[idx+4:]
-
-    def getPath(self):
-        """Returns the path of the request"""
-        return self._path
-
-    def __getattr__(self, attr):
-        return getattr(self._response, attr)
-
-
-def _getDefaultSkin():
-    """Returns the current default skin as an interface."""
-    adapters = zapi.getService(zapi.servicenames.Adapters)
-    skin = adapters.lookup((IBrowserRequest,), IDefaultSkin, '')
-    return skin or IDefaultBrowserLayer
-
-
-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""")
-
-class FunctionalTestSetup(object):
-    """Keeps shared state across several functional test cases."""
-
-    __shared_state = { '_init': False }
-
-    def __init__(self, config_file=None):
-        """Initializes Zope 3 framework.
-
-        Creates a volatile memory storage.  Parses Zope3 configuration files.
-        """
-        self.__dict__ = self.__shared_state
-
-        if not self._init:
-
-            # Make sure unit tests are cleaned up
-            zope.app.tests.setup.placefulSetUp()
-            zope.app.tests.setup.placefulTearDown()
-
-            if not config_file:
-                config_file = 'ftesting.zcml'
-            self.log = StringIO()
-            # Make it silent but keep the log available for debugging
-            logging.root.addHandler(logging.StreamHandler(self.log))
-            self.base_storage = DemoStorage("Memory Storage")
-            self.db = DB(self.base_storage)
-            self.app = Debugger(self.db, config_file)
-            self.connection = None
-            self._config_file = config_file
-            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)
-            FunctionalTestSetup().connection = None
-            
-        elif config_file and config_file != self._config_file:
-            # Running different tests with different configurations is not
-            # supported at the moment
-            raise NotImplementedError('Already configured'
-                                      ' with a different config file')
-
-    def setUp(self):
-        """Prepares for a functional test case."""
-        # Tear down the old demo storage (if any) and create a fresh one
-        abort()
-        self.db.close()
-        storage = DemoStorage("Demo Storage", self.base_storage)
-        self.db = self.app.db = DB(storage)
-        self.connection = None
-
-    def tearDown(self):
-        """Cleans up after a functional test case."""
-        abort()
-        if self.connection:
-            self.connection.close()
-            self.connection = None
-        self.db.close()
-
-    def getRootFolder(self):
-        """Returns the Zope root folder."""
-        if not self.connection:
-            self.connection = self.db.open()
-        root = self.connection.root()
-        return root[ZopePublication.root_name]
-
-    def getApplication(self):
-        """Returns the Zope application instance."""
-        return self.app
-
-
-class FunctionalTestCase(unittest.TestCase):
-    """Functional test case."""
-
-    def setUp(self):
-        """Prepares for a functional test case."""
-        super(FunctionalTestCase, self).setUp()
-        FunctionalTestSetup().setUp()
-
-    def tearDown(self):
-        """Cleans up after a functional test case."""
-
-        FunctionalTestSetup().tearDown()
-        super(FunctionalTestCase, self).tearDown()
-
-    def getRootFolder(self):
-        """Returns the Zope root folder."""
-        return FunctionalTestSetup().getRootFolder()
-
-    def commit(self):
-        commit()
-
-    def abort(self):
-        abort()
-
-class BrowserTestCase(FunctionalTestCase):
-    """Functional test case for Browser requests."""
-
-    def setUp(self):
-        super(BrowserTestCase, self).setUp()
-        # Somewhere to store cookies between consecutive requests
-        self.cookies = SimpleCookie()
-
-    def tearDown(self):
-        del self.cookies
-
-        self.setSite(None)
-        super(BrowserTestCase, self).tearDown()
-
-    def setSite(self, site):
-        """Set the site which will be used to look up local services"""
-        setSite(site)
-
-    def getSite(self):
-        """Returns the site which is used to look up local services"""
-        return getSite()
-
-    def makeRequest(self, path='', basic=None, form=None, env={},
-                    outstream=None):
-        """Creates a new request object.
-
-        Arguments:
-          path   -- the path to be traversed (e.g. "/folder1/index.html")
-          basic  -- basic HTTP authentication credentials ("user:password")
-          form   -- a dictionary emulating a form submission
-                    (Note that field values should be Unicode strings)
-          env    -- a dictionary of additional environment variables
-                    (You can emulate HTTP request header
-                       X-Header: foo
-                     by adding 'HTTP_X_HEADER': 'foo' to env)
-          outstream -- a stream where the HTTP response will be written
-        """
-        if outstream is None:
-            outstream = HTTPTaskStub()
-        environment = {"HTTP_HOST": 'localhost',
-                       "HTTP_REFERER": 'localhost',
-                       "HTTP_COOKIE": self.__http_cookie(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())
-        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.
-
-        Arguments are the same as in makeRequest with the following exception:
-          handle_errors  -- if False (default), exceptions will not be caught
-                            if True, exceptions will return a formatted error
-                            page.
-
-        Returns the response object enhanced with the following methods:
-          getOutput()    -- returns the full HTTP output as a string
-          getBody()      -- returns the full response body as a string
-          getPath()      -- returns the path used in the request
-        """
-        outstream = HTTPTaskStub()
-        old_site = self.getSite()
-        self.setSite(None)
-        # A cookie header has been sent - ensure that future requests
-        # in this test also send the cookie, as this is what browsers do.
-        # 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'])
-            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'])
-        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.setSite(old_site)
-        return response
-
-    def checkForBrokenLinks(self, body, path, basic=None):
-        """Looks for broken links in a page by trying to traverse relative
-        URIs.
-        """
-        if not body: return
-
-        old_site = self.getSite()
-        self.setSite(None)
-
-        from htmllib import HTMLParser
-        from formatter import NullFormatter
-        class SimpleHTMLParser(HTMLParser):
-            def __init__(self, fmt, base):
-                HTMLParser.__init__(self, fmt)
-                self.base = base
-            def do_base(self, attrs):
-                self.base = dict(attrs).get('href', self.base)
-
-        parser = SimpleHTMLParser(NullFormatter(), path)
-        parser.feed(body)
-        parser.close()
-        base = parser.base
-        while not base.endswith('/'):
-            base = base[:-1]
-        if base.startswith('http://localhost/'):
-            base = base[len('http://localhost/') - 1:]
-
-        errors = []
-        for a in parser.anchorlist:
-            if a.startswith('http://localhost/'):
-                a = a[len('http://localhost/') - 1:]
-            elif a.find(':') != -1:
-                # Assume it is an external link
-                continue
-            elif not a.startswith('/'):
-                a = base + a
-            if a.find('#') != -1:
-                a = a[:a.index('#') - 1]
-            # XXX what about queries (/path/to/foo?bar=baz&etc)?
-            request = None
-            try:
-                try:
-                    request = self.makeRequest(a, basic=basic)
-                    publication = request.publication
-                    request.processInputs()
-                    publication.beforeTraversal(request)
-                    object = publication.getApplication(request)
-                    object = request.traverse(object)
-                    publication.afterTraversal(request, object)
-                except (KeyError, NameError, AttributeError, Unauthorized, Forbidden):
-                    e = traceback.format_exception_only(*sys.exc_info()[:2])[-1]
-                    errors.append((a, e.strip()))
-            finally:
-                publication.endRequest(request, object)
-                self.setSite(old_site)
-                # Bad Things(TM) related to garbage collection and special
-                # __del__ methods happen if request.close() is not called here
-                if request:
-                    request.close()
-        if errors:
-            self.fail("%s contains broken links:\n" % path
-                      + "\n".join(["  %s:\t%s" % (a, e) for a, e in errors]))
-
-
-class HTTPTestCase(FunctionalTestCase):
-    """Functional test case for HTTP requests."""
-
-    def makeRequest(self, path='', basic=None, form=None, env={},
-                    instream=None, outstream=None):
-        """Creates a new request object.
-
-        Arguments:
-          path   -- the path to be traversed (e.g. "/folder1/index.html")
-          basic  -- basic HTTP authentication credentials ("user:password")
-          form   -- a dictionary emulating a form submission
-                    (Note that field values should be Unicode strings)
-          env    -- a dictionary of additional environment variables
-                    (You can emulate HTTP request header
-                       X-Header: foo
-                     by adding 'HTTP_X_HEADER': 'foo' to env)
-          instream  -- a stream from where the HTTP request will be read
-          outstream -- a stream where the HTTP response will be written
-        """
-        if outstream is None:
-            outstream = HTTPTaskStub()
-        if instream is None:
-            instream = ''
-        environment = {"HTTP_HOST": 'localhost',
-                       "HTTP_REFERER": 'localhost'}
-        environment.update(env)
-        app = FunctionalTestSetup().getApplication()
-        request = app._request(path, instream, outstream,
-                               environment=environment,
-                               basic=basic, form=form,
-                               request=HTTPRequest, publication=HTTPPublication)
-        return request
-
-    def publish(self, path, basic=None, form=None, env={},
-                handle_errors=False, request_body=''):
-        """Renders an object at a given location.
-
-        Arguments are the same as in makeRequest with the following exception:
-          handle_errors  -- if False (default), exceptions will not be caught
-                            if True, exceptions will return a formatted error
-                            page.
-
-        Returns the response object enhanced with the following methods:
-          getOutput()    -- returns the full HTTP output as a string
-          getBody()      -- returns the full response body as a string
-          getPath()      -- returns the path used in the request
-        """
-        outstream = HTTPTaskStub()
-        request = self.makeRequest(path, basic=basic, form=form, env=env,
-                                   instream=request_body, outstream=outstream)
-        response = ResponseWrapper(request.response, outstream, path)
-        publish(request, handle_errors=handle_errors)
-        return response
-
-
-class HTTPHeaderOutput:
-
-    zope.interface.implements(zope.publisher.interfaces.http.IHeaderOutput)
-
-    def __init__(self, protocol, omit):
-        self.headers = {}
-        self.headersl = []
-        self.protocol = protocol
-        self.omit = omit
-    
-    def setResponseStatus(self, status, reason):
-        self.status, self.reason = status, reason
-
-    def setResponseHeaders(self, mapping):
-        self.headers.update(dict(
-            [('-'.join([s.capitalize() for s in name.split('-')]), v)
-             for name, v in mapping.items()
-             if name.lower() not in self.omit]
-        ))
-
-    def appendResponseHeaders(self, lst):
-        headers = [split_header(header) for header in lst]
-        self.headersl.extend(
-            [('-'.join([s.capitalize() for s in name.split('-')]), v)
-             for name, v in headers
-             if name.lower() not in self.omit]
-        )
-
-    def __str__(self):
-        out = ["%s: %s" % header for header in self.headers.items()]
-        out.extend(["%s: %s" % header for header in self.headersl])
-        out.sort()
-        out.insert(0, "%s %s %s" % (self.protocol, self.status, self.reason))
-        return '\n'.join(out)
-
-class DocResponseWrapper(ResponseWrapper):
-    """Response Wrapper for use in doc tests
-    """
-
-    def __init__(self, response, outstream, path, header_output):
-        ResponseWrapper.__init__(self, response, outstream, path)
-        self.header_output = header_output
-
-    def __str__(self):
-        body = self.getOutput()
-        if body:
-            return "%s\n\n%s" % (self.header_output, body)
-        return "%s\n" % (self.header_output)
-
-    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+): (.+)$')
-def split_header(header):
-    return headerre.match(header).group(1, 2)
-
-basicre = re.compile('Basic (.+)?:(.+)?$')
-def auth_header(header):
-    match = basicre.match(header)
-    if match:
-        import base64
-        u, p = match.group(1, 2)
-        if u is None:
-            u = ''
-        if p is None:
-            p = ''
-        auth = base64.encodestring('%s:%s' % (u, p))
-        return 'Basic %s' % auth[:-1]
-    return header
-
-def getRootFolder():
-    return FunctionalTestSetup().getRootFolder()
-
-def sync():
-    getRootFolder()._p_jar.sync()
-
-#
-# Sample functional test case
-#
-
-class SampleFunctionalTest(BrowserTestCase):
-
-    def testRootPage(self):
-        response = self.publish('/')
-        self.assertEquals(response.getStatus(), 200)
-
-    def testRootPage_preferred_languages(self):
-        response = self.publish('/', env={'HTTP_ACCEPT_LANGUAGE': 'en'})
-        self.assertEquals(response.getStatus(), 200)
-
-    def testNotExisting(self):
-        response = self.publish('/nosuchthing', handle_errors=True)
-        self.assertEquals(response.getStatus(), 404)
-
-    def testLinks(self):
-        response = self.publish('/')
-        self.assertEquals(response.getStatus(), 200)
-        self.checkForBrokenLinks(response.getBody(), response.getPath())
-
-
-def sample_test_suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(SampleFunctionalTest))
-    return suite
-
-def FunctionalDocFileSuite(*paths, **kw):
-    globs = kw.setdefault('globs', {})
-    globs['http'] = http
-    globs['getRootFolder'] = getRootFolder
-    globs['sync'] = sync
-
-    kw['package'] = doctest._normalize_module(kw.get('package'))
-
-    kwsetUp = kw.get('setUp')
-    def setUp(test):
-        FunctionalTestSetup().setUp()
-        
-        if kwsetUp is not None:
-            kwsetUp(test)
-    kw['setUp'] = setUp
-
-    kwtearDown = kw.get('tearDown')
-    def tearDown(test):
-        if kwtearDown is not None:
-            kwtearDown(test)
-        FunctionalTestSetup().tearDown()
-    kw['tearDown'] = tearDown
-
-    kw['optionflags'] = doctest.ELLIPSIS | doctest.REPORT_NDIFF
-
-    return doctest.DocFileSuite(*paths, **kw)
-
-if __name__ == '__main__':
-    unittest.main()

Deleted: Zope3/branches/srichter-blow-services/src/zope/app/tests/placelesssetup.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/tests/placelesssetup.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/tests/placelesssetup.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1,69 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 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.
-#
-##############################################################################
-"""Unit test logic for setting up and tearing down basic infrastructure
-
-$Id$
-"""
-from zope.app.tests import ztapi
-from zope.schema.vocabulary import setVocabularyRegistry
-from zope.component.tests.placelesssetup \
-    import PlacelessSetup as CAPlacelessSetup
-from zope.app.event.tests.placelesssetup \
-    import PlacelessSetup as EventPlacelessSetup
-from zope.app.i18n.tests.placelesssetup \
-    import PlacelessSetup as I18nPlacelessSetup
-from zope.app.container.tests.placelesssetup \
-    import PlacelessSetup as ContainerPlacelessSetup
-from zope.app.security._protections import protect
-from zope.app.traversing.browser.interfaces import IAbsoluteURL
-from zope.app.traversing.browser.absoluteurl import AbsoluteURL
-
-class PlacelessSetup(CAPlacelessSetup,
-                     EventPlacelessSetup,
-                     I18nPlacelessSetup,
-                     ContainerPlacelessSetup
-                     ):
-
-    def setUp(self, doctesttest=None):
-        CAPlacelessSetup.setUp(self)
-        ContainerPlacelessSetup.setUp(self)
-        EventPlacelessSetup.setUp(self)
-        I18nPlacelessSetup.setUp(self)
-        # Register app-specific security declarations
-        protect()
-
-        ztapi.browserView(None, 'absolute_url', AbsoluteURL)
-        ztapi.browserViewProviding(None, AbsoluteURL, IAbsoluteURL)
-
-        from zope.app.security.tests import addCheckerPublic
-        addCheckerPublic()
-
-        from zope.security.management import newInteraction
-        newInteraction()
-
-        setVocabularyRegistry(None)
-
-
-ps = PlacelessSetup()
-setUp = ps.setUp
-
-def tearDown():
-    tearDown_ = ps.tearDown
-    def tearDown(doctesttest=None):
-        tearDown_()
-    return tearDown
-
-tearDown = tearDown()
-
-del ps

Deleted: Zope3/branches/srichter-blow-services/src/zope/app/tests/setup.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/tests/setup.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/tests/setup.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1,206 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 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.
-#
-##############################################################################
-"""Setting up an environment for testing context-dependent objects
-
-$Id$
-"""
-
-import zope.component
-import zope.interface
-from zope.app import zapi
-from zope.app.tests import ztapi
-from zope.interface import classImplements
-
-#------------------------------------------------------------------------
-# Annotations
-from zope.app.annotation.attribute import AttributeAnnotations
-from zope.app.annotation.interfaces import IAnnotations
-from zope.app.annotation.interfaces import IAttributeAnnotatable
-def setUpAnnotations():
-    ztapi.provideAdapter(IAttributeAnnotatable, IAnnotations,
-                         AttributeAnnotations)
-
-#------------------------------------------------------------------------
-# Dependencies
-from zope.app.dependable import Dependable
-from zope.app.dependable.interfaces import IDependable
-def setUpDependable():
-    ztapi.provideAdapter(IAttributeAnnotatable, IDependable,
-                         Dependable)
-
-#------------------------------------------------------------------------
-# Traversal
-from zope.app.traversing.browser.interfaces import IAbsoluteURL
-from zope.app.traversing.browser import SiteAbsoluteURL, AbsoluteURL
-from zope.app.container.traversal import ContainerTraversable
-from zope.app.container.interfaces import ISimpleReadContainer
-from zope.app.traversing.interfaces import IContainmentRoot
-from zope.app.traversing.interfaces import IPhysicallyLocatable
-from zope.app.traversing.interfaces import ITraverser, ITraversable
-from zope.app.traversing.adapters import DefaultTraversable
-from zope.app.traversing.adapters import Traverser, RootPhysicallyLocatable
-from zope.app.location.traversing import LocationPhysicallyLocatable
-from zope.app.traversing.namespace import etc
-
-def setUpTraversal():
-    ztapi.provideAdapter(None, ITraverser, Traverser)
-    ztapi.provideAdapter(None, ITraversable, DefaultTraversable)
-
-    ztapi.provideAdapter(
-        ISimpleReadContainer, ITraversable, ContainerTraversable)
-    ztapi.provideAdapter(
-        None, IPhysicallyLocatable, LocationPhysicallyLocatable)
-    ztapi.provideAdapter(
-        IContainmentRoot, IPhysicallyLocatable, RootPhysicallyLocatable)
-
-    # set up etc namespace
-    ztapi.provideAdapter(None, ITraversable, etc, name="etc")
-    ztapi.provideView(None, None, ITraversable, "etc", etc)
-
-    ztapi.browserView(None, "absolute_url", AbsoluteURL)
-    ztapi.browserView(IContainmentRoot, "absolute_url", SiteAbsoluteURL)
-
-    ztapi.browserView(None, '', AbsoluteURL, providing=IAbsoluteURL)
-    ztapi.browserView(IContainmentRoot, '', SiteAbsoluteURL,
-                      providing=IAbsoluteURL)
-
-
-#------------------------------------------------------------------------
-# Use registration
-from zope.app.registration.interfaces import IAttributeRegisterable
-from zope.app.registration.interfaces import IRegistered
-from zope.app.registration.registration import Registered
-def setUpRegistered():
-    ztapi.provideAdapter(IAttributeRegisterable, IRegistered,
-                         Registered)
-
-#------------------------------------------------------------------------
-# Service service lookup
-from zope.app.component.localservice import serviceServiceAdapter
-from zope.app.registration.interfaces import IRegistrationActivatedEvent
-from zope.app.registration.interfaces import IRegistrationDeactivatedEvent
-from zope.app.site.service import handleActivated, handleDeactivated
-from zope.component.interfaces import IServiceService
-from zope.interface import Interface
-def setUpServiceService():
-    ztapi.subscribe((IRegistrationActivatedEvent,), None, handleActivated)
-    ztapi.subscribe((IRegistrationDeactivatedEvent,), None, handleDeactivated)
-    ztapi.provideAdapter(Interface, IServiceService, serviceServiceAdapter)
-
-#------------------------------------------------------------------------
-# Placeful setup
-import zope.app.component.hooks
-from zope.app.tests.placelesssetup import setUp as placelessSetUp
-from zope.app.tests.placelesssetup import tearDown as placelessTearDown
-def placefulSetUp(site=False):
-    placelessSetUp()
-    zope.app.component.hooks.setHooks()
-    setUpAnnotations()
-    setUpDependable()
-    setUpTraversal()
-    setUpRegistered()
-    setUpServiceService()
-
-    if site:
-        site = rootFolder()
-        createServiceManager(site, setsite=True)
-        return site
-
-from zope.app.component.hooks import setSite
-def placefulTearDown():
-    placelessTearDown()
-    zope.app.component.hooks.resetHooks()
-    setSite()
-
-
-from zope.app.folder import Folder, rootFolder
-
-def buildSampleFolderTree():
-    # set up a reasonably complex folder structure
-    #
-    #     ____________ rootFolder ____________
-    #    /                                    \
-    # folder1 __________________            folder2
-    #   |                       \             |
-    # folder1_1 ____           folder1_2    folder2_1
-    #   |           \            |            |
-    # folder1_1_1 folder1_1_2  folder1_2_1  folder2_1_1
-
-    root = rootFolder()
-    root['folder1'] = Folder()
-    root['folder1']['folder1_1'] = Folder()
-    root['folder1']['folder1_1']['folder1_1_1'] = Folder()
-    root['folder1']['folder1_1']['folder1_1_2'] = Folder()
-    root['folder1']['folder1_2'] = Folder()
-    root['folder1']['folder1_2']['folder1_2_1'] = Folder()
-    root['folder2'] = Folder()
-    root['folder2']['folder2_1'] = Folder()
-    root['folder2']['folder2_1']['folder2_1_1'] = Folder()
-
-    return root
-
-
-from zope.app.site.service import ServiceManager
-from zope.app.site.interfaces import ISite
-def createServiceManager(folder, setsite=False):
-    if not ISite.providedBy(folder):
-        folder.setSiteManager(ServiceManager(folder))
-    if setsite:
-        setSite(folder)
-    return zapi.traverse(folder, "++etc++site")
-
-from zope.app.site.service import ServiceRegistration
-from zope.app.site.interfaces import ISimpleService
-from zope.app.registration.interfaces import ActiveStatus
-
-def addService(servicemanager, name, service, suffix=''):
-    """Add a service to a service manager
-
-    This utility is useful for tests that need to set up services.
-    """
-    # Most local services implement ISimpleService in ZCML; therefore make
-    # sure we got it here as well.
-    zope.interface.directlyProvides(service, ISimpleService)
-
-    default = zapi.traverse(servicemanager, 'default')
-    default[name+suffix] = service
-    registration = ServiceRegistration(name, service, default)
-    key = default.getRegistrationManager().addRegistration(registration)
-    zapi.traverse(default.getRegistrationManager(), key).status = ActiveStatus
-    return default[name+suffix]
-
-from zope.app.utility import UtilityRegistration
-
-def addUtility(servicemanager, name, iface, utility, suffix=''):
-    """Add a utility to a service manager
-
-    This utility is useful for tests that need to set up utilities.
-    """
-    
-    folder_name = (name or (iface.__name__ + 'Utility')) + suffix
-    default = zapi.traverse(servicemanager, 'default')
-    default[folder_name] = utility
-    registration = UtilityRegistration(name, iface, default[folder_name])
-    key = default.getRegistrationManager().addRegistration(registration)
-    zapi.traverse(default.getRegistrationManager(), key).status = ActiveStatus
-    return default[folder_name]
-
-def createStandardServices(folder):
-    '''Create a bunch of standard placeful services
-
-    Well, uh, 0
-    '''
-    sm = createServiceManager(folder)
-
-

Deleted: Zope3/branches/srichter-blow-services/src/zope/app/tests/test.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/tests/test.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/tests/test.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1,1242 +0,0 @@
-#! /usr/bin/env python2.3
-##############################################################################
-#
-# Copyright (c) 2001, 2002 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.
-#
-##############################################################################
-"""test.py [-abBcdDfFgGhklLmMPprstTuUv] [modfilter [testfilter...]]
-
-Find and run tests written using the unittest module.
-
-The test runner searches for Python modules that contain test suites.
-It collects those suites, and runs the tests.  There are many options
-for controlling how the tests are run.  There are options for using
-the debugger, reporting code coverage, and checking for refcount problems.
-
-The test runner uses the following rules for finding tests to run.  It
-searches for packages and modules that contain "tests" as a component
-of the name, e.g. "frob.tests.nitz" matches this rule because tests is
-a sub-package of frob.  Within each "tests" package, it looks for
-modules that begin with the name "test."  For each test module, it
-imports the module and calls the module's test_suite() function, which must
-return a unittest TestSuite object.
-
-Options can be specified as command line arguments (see below). However,
-options may also be specified in a file named 'test.config', a Python
-script which, if found, will be executed before the command line
-arguments are processed.
-
-The test.config script should specify options by setting zero or more of the
-global variables: LEVEL, BUILD, and other capitalized variable names found in
-the test runner script (see the list of global variables in process_args().).
-
-
--a level
---at-level level
---all
-    Run the tests at the given level.  Any test at a level at or below
-    this is run, any test at a level above this is not run.  Level 0
-    runs all tests.  The default is to run tests at level 1.  --all is
-    a shortcut for -a 0.
-
--b
---build
-    Run "python setup.py build" before running tests, where "python"
-    is the version of python used to run test.py.  Highly recommended.
-    Tests will be run from the build directory.
-
--B
---build-inplace
-    Run "python setup.py build_ext -i" before running tests.  Tests will be
-    run from the source directory.
-
--c
---pychecker
-    use pychecker
-
--d
---debug
-    Instead of the normal test harness, run a debug version which
-    doesn't catch any exceptions.  This is occasionally handy when the
-    unittest code catching the exception doesn't work right.
-    Unfortunately, the debug harness doesn't print the name of the
-    test, so Use With Care.
-
--D
---debug-inplace
-    Works like -d, except that it loads pdb when an exception occurs.
-
---dir directory
--s directory
-    Option to limit where tests are searched for. This is important
-    when you *really* want to limit the code that gets run.  This can
-    be specified more than once to run tests in two different parts of
-    the source tree.
-    For example, if refactoring interfaces, you don't want to see the way
-    you have broken setups for tests in other packages. You *just* want to
-    run the interface tests.
-
--f
---skip-unit
-    Run functional tests but not unit tests.
-    Note that functional tests will be skipped if the module
-    zope.app.tests.functional cannot be imported.
-    Functional tests also expect to find the file ftesting.zcml,
-    which is used to configure the functional-test run.
-
--F
-    DEPRECATED. Run both unit and functional tests.
-    This option is deprecated, because this is the new default mode.
-    Note that functional tests will be skipped if the module
-    zope.app.tests.functional cannot be imported.
-
--g threshold
---gc-threshold threshold
-    Set the garbage collector generation0 threshold.  This can be used
-    to stress memory and gc correctness.  Some crashes are only
-    reproducible when the threshold is set to 1 (agressive garbage
-    collection).  Do "-g 0" to disable garbage collection altogether.
-
--G gc_option
---gc-option gc_option
-    Set the garbage collection debugging flags.  The argument must be one
-    of the DEBUG_ flags defined bythe Python gc module.  Multiple options
-    can be specified by using "-G OPTION1 -G OPTION2."
-
--k
---keepbytecode
-    Do not delete all stale bytecode before running tests
-
--l test_root
---libdir test_root
-    Search for tests starting in the specified start directory
-    (useful for testing components being developed outside the main
-    "src" or "build" trees).
-
--L
---loop
-    Keep running the selected tests in a loop.  You may experience
-    memory leakage.
-
---module modfilter
-    Provide a module filter (see modfilter below)
-
--N n
---repeat n
-    Run the selected tests n times.
-
--m
--M  minimal GUI. See -U.
-
--P
---profile
-    Run the tests under hotshot and display the top 50 stats, sorted by
-    cumulative time and number of calls.
-
--p
---progress
-    Show running progress.  It can be combined with -v or -vv.
-
--r
---refcount
-    Look for refcount problems.
-    This requires that Python was built --with-pydebug.
-
--1
---report-only-first-doctest-failure
-
-   Report only the first failure in a doctest. (Examples after the
-   failure are still executed, in case they do any cleanup.)
-
--t
---top-fifty
-    Time the individual tests and print a list of the top 50, sorted from
-    longest to shortest.
-
---test testfilter
-    Provide a test filter (see testfilter below)
-
---times n
---times outfile
-    With an integer argument, time the tests and print a list of the top <n>
-    tests, sorted from longest to shortest.
-    With a non-integer argument, specifies a file to which timing information
-    is to be printed.
-
--T
---trace
-    Use the trace module from Python for code coverage.  The current
-    utility writes coverage files to a directory named `coverage' that
-    is parallel to `build'.  It also prints a summary to stdout.
-
--u
---skip-functional
-    CHANGED. Run unit tests but not functional tests.
-    Note that the meaning of -u is changed from its former meaning,
-    which is now specified by -U or --gui.
-
--U
---gui
-    Use the PyUnit GUI instead of output to the command line.  The GUI
-    imports tests on its own, taking care to reload all dependencies
-    on each run.  The debug (-d), verbose (-v), progress (-p), and
-    Loop (-L) options will be ignored.  The testfilter filter is also
-    not applied.
-
--m
--M
---minimal-gui
-    Note: -m is DEPRECATED in favour of -M or --minimal-gui.
-    -m starts the gui minimized.  Double-clicking the progress bar
-    will start the import and run all tests.
-
-
--v
---verbose
-    Verbose output.  With one -v, unittest prints a dot (".") for each
-    test run.  With -vv, unittest prints the name of each test (for
-    some definition of "name" ...).  With no -v, unittest is silent
-    until the end of the run, except when errors occur.
-
-    When -p is also specified, the meaning of -v is slightly
-    different.  With -p and no -v only the percent indicator is
-    displayed.  With -p and -v the test name of the current test is
-    shown to the right of the percent indicator.  With -p and -vv the
-    test name is not truncated to fit into 80 columns and it is not
-    cleared after the test finishes.
-
-
-modfilter
-testfilter...
-    Case-sensitive regexps to limit which tests are run, used in search
-    (not match) mode.
-    In an extension of Python regexp notation, a leading "!" is stripped
-    and causes the sense of the remaining regexp to be negated (so "!bc"
-    matches any string that does not match "bc", and vice versa).
-    By default these act like ".", i.e. nothing is excluded.
-
-    modfilter is applied to a test file's path, starting at "build" and
-    including (OS-dependent) path separators.  Additional modfilters
-    can be specified with the --module option; modules are matched if
-    they match at least one modfilter.
-
-    testfilter is applied to the (method) name of the unittest methods
-    contained in the test files whose paths modfilter matched.
-    Additional testfilters can be specified with the --test option;
-    methods are matched if they match at least one testfilter.
-
-Extreme (yet useful) examples:
-
-    test.py -vvb . "^testWriteClient$"
-
-    Builds the project silently, then runs unittest in verbose mode on all
-    tests whose names are precisely "testWriteClient".  Useful when
-    debugging a specific test.
-
-    test.py -vvb . "!^testWriteClient$"
-
-    As before, but runs all tests whose names aren't precisely
-    "testWriteClient".  Useful to avoid a specific failing test you don't
-    want to deal with just yet.
-
-    test.py -M . "!^testWriteClient$"
-
-    As before, but now opens up a minimized PyUnit GUI window (only showing
-    the progress bar).  Useful for refactoring runs where you continually want
-    to make sure all tests still pass.
-
-$Id$
-"""
-import gc
-import hotshot, hotshot.stats
-import logging
-import os
-import re
-import pdb
-import sys
-import threading    # just to get at Thread objects created by tests
-import time
-import traceback
-import unittest
-import warnings
-
-FTESTING = "ftesting.zcml"
-
-def set_trace_doctest(stdin=sys.stdin, stdout=sys.stdout, trace=pdb.set_trace):
-    sys.stdin = stdin
-    sys.stdout = stdout
-    trace()
-
-pdb.set_trace_doctest = set_trace_doctest
-
-from distutils.util import get_platform
-
-PLAT_SPEC = "%s-%s" % (get_platform(), sys.version[0:3])
-
-class ImmediateTestResult(unittest._TextTestResult):
-
-    __super_init = unittest._TextTestResult.__init__
-    __super_startTest = unittest._TextTestResult.startTest
-    __super_printErrors = unittest._TextTestResult.printErrors
-
-    def __init__(self, stream, descriptions, verbosity,
-                 count=None, progress=False):
-        self.__super_init(stream, descriptions, verbosity)
-        self._progress = progress
-        self._progressWithNames = False
-        self.count = count
-        self._testtimes = {}
-        if progress and verbosity == 1:
-            self.dots = False
-            self._progressWithNames = True
-            self._lastWidth = 0
-            self._maxWidth = 80
-            try:
-                import curses
-            except ImportError:
-                pass
-            else:
-                curses.setupterm()
-                self._maxWidth = curses.tigetnum('cols')
-            self._maxWidth -= len("xxxx/xxxx (xxx.x%): ") + 1
-
-    def stopTest(self, test):
-        self._testtimes[test] = time.time() - self._testtimes[test]
-        if gc.garbage:
-            print "The following test left garbage:"
-            print test
-            print gc.garbage
-            # XXX Perhaps eat the garbage here, so that the garbage isn't
-            #     printed for every subsequent test.
-
-        # Did the test leave any new threads behind?
-        new_threads = [t for t in threading.enumerate()
-                         if (t.isAlive()
-                             and
-                             t not in self._threads)]
-        if new_threads:
-            print "The following test left new threads behind:"
-            print test
-            print "New thread(s):", new_threads
-
-    def print_times(self, stream, count=None):
-        results = self._testtimes.items()
-        results.sort(lambda x, y: cmp(y[1], x[1]))
-        if count:
-            n = min(count, len(results))
-            if n:
-                print >>stream, "Top %d longest tests:" % n
-        else:
-            n = len(results)
-        if not n:
-            return
-        for i in range(n):
-            print >>stream, "%6dms" % int(results[i][1] * 1000), results[i][0]
-
-    def _print_traceback(self, msg, err, test, errlist):
-        if self.showAll or self.dots or self._progress:
-            self.stream.writeln("\n")
-            self._lastWidth = 0
-
-        tb = "".join(traceback.format_exception(*err))
-        self.stream.writeln(msg)
-        self.stream.writeln(tb)
-        errlist.append((test, tb))
-
-    def startTest(self, test):
-        if self._progress:
-            self.stream.write("\r%4d" % (self.testsRun + 1))
-            if self.count:
-                self.stream.write("/%d (%5.1f%%)" % (self.count,
-                                  (self.testsRun + 1) * 100.0 / self.count))
-            if self.showAll:
-                self.stream.write(": ")
-            elif self._progressWithNames:
-                # XXX will break with multibyte strings
-                name = self.getShortDescription(test)
-                width = len(name)
-                if width < self._lastWidth:
-                    name += " " * (self._lastWidth - width)
-                self.stream.write(": %s" % name)
-                self._lastWidth = width
-            self.stream.flush()
-        self._threads = threading.enumerate()
-
-        self.__super_startTest(test)
-        # the super version can't count. ;)
-        self.testsRun += test.countTestCases() - 1
-
-        self._testtimes[test] = time.time()
-
-
-    def getShortDescription(self, test):
-        s = self.getDescription(test)
-        if len(s) > self._maxWidth:
-            pos = s.find(" (")
-            if pos >= 0:
-                w = self._maxWidth - (pos + 5)
-                if w < 1:
-                    # first portion (test method name) is too long
-                    s = s[:self._maxWidth-3] + "..."
-                else:
-                    pre = s[:pos+2]
-                    post = s[-w:]
-                    s = "%s...%s" % (pre, post)
-        return s[:self._maxWidth]
-
-    def addError(self, test, err):
-        if self._progress:
-            self.stream.write("\r")
-        self._print_traceback("Error in test %s" % test, err,
-                              test, self.errors)
-
-    def addFailure(self, test, err):
-        if self._progress:
-            self.stream.write("\r")
-        self._print_traceback("Failure in test %s" % test, err,
-                              test, self.failures)
-
-    def printErrors(self):
-        if VERBOSE < 2:
-            # We'be output errors as they occured. Outputing them a second
-            # time is just annoying. 
-            return
-
-        if self._progress and not (self.dots or self.showAll):
-            self.stream.writeln()
-        self.__super_printErrors()
-
-    def printErrorList(self, flavor, errors):
-        for test, err in errors:
-            self.stream.writeln(self.separator1)
-            self.stream.writeln("%s: %s" % (flavor, self.getDescription(test)))
-            self.stream.writeln(self.separator2)
-            self.stream.writeln(err)
-
-
-class ImmediateTestRunner(unittest.TextTestRunner):
-
-    __super_init = unittest.TextTestRunner.__init__
-
-    def __init__(self, **kwarg):
-        progress = kwarg.get("progress")
-        if progress is not None:
-            del kwarg["progress"]
-        profile = kwarg.get("profile")
-        if profile is not None:
-            del kwarg["profile"]
-        self.__super_init(**kwarg)
-        self._progress = progress
-        self._profile = profile
-        # Create the test result here, so that we can add errors if
-        # the test suite search process has problems.  The count
-        # attribute must be set in run(), because we won't know the
-        # count until all test suites have been found.
-        self.result = ImmediateTestResult(
-            self.stream, self.descriptions, self.verbosity,
-            progress=self._progress)
-
-    def _makeResult(self):
-        # Needed base class run method.
-        return self.result
-
-    def run(self, test):
-        self.result.count = test.countTestCases()
-        if self._profile:
-            prof = hotshot.Profile("tests_profile.prof")
-            args = (self, test)
-            r = prof.runcall(unittest.TextTestRunner.run, *args)
-            prof.close()
-            stats = hotshot.stats.load("tests_profile.prof")
-            stats.sort_stats('cumulative', 'calls')
-            stats.print_stats(50)
-            return r
-        return unittest.TextTestRunner.run(self, test)
-
-# setup list of directories to put on the path
-class PathInit(object):
-    def __init__(self, build, build_inplace, libdir=None):
-        self.inplace = None
-        # Figure out if we should test in-place or test in-build.  If the -b
-        # or -B option was given, test in the place we were told to build in.
-        # Otherwise, we'll look for a build directory and if we find one,
-        # we'll test there, otherwise we'll test in-place.
-        if build:
-            self.inplace = build_inplace
-        if self.inplace is None:
-            # Need to figure it out
-            if os.path.isdir(os.path.join("build", "lib.%s" % PLAT_SPEC)):
-                self.inplace = False
-            else:
-                self.inplace = True
-        # Calculate which directories we're going to add to sys.path, and cd
-        # to the appropriate working directory
-        self.org_cwd = os.getcwd()
-        if self.inplace:
-            self.libdir = "src"
-        else:
-            self.libdir = "lib.%s" % PLAT_SPEC
-            os.chdir("build")
-        # Hack sys.path
-        self.cwd = os.getcwd()
-        sys.path.insert(0, os.path.join(self.cwd, self.libdir))
-        # Hack again for external products.
-        kind = functional and "FUNCTIONAL" or "UNIT"
-        if libdir:
-            extra = os.path.join(self.org_cwd, libdir)
-            print "Running %s tests from %s" % (kind, extra)
-            self.libdir = extra
-            sys.path.insert(0, extra)
-        else:
-            print "Running %s tests from %s" % (kind, self.cwd)
-
-def match(rxlist, s):
-    if not rxlist:
-        return True
-    for rx in rxlist:
-        if rx[0] == "!":
-            matched = re.search(rx[1:], s) is None
-        else:
-            matched = re.search(rx, s) is not None
-        if matched:
-            return True
-    return False
-
-class TestFileFinder(object):
-
-    EMPTY_FILE_LISTS = ([], ["{arch}"], ["CVS"], ["_darcs"], [".svn"])
-
-    def __init__(self, prefix):
-        self.files = []
-        self._plen = len(prefix)
-        if not prefix.endswith(os.sep):
-            self._plen += 1
-        if functional:
-            self.dirname = "ftests"
-        else:
-            self.dirname = "tests"
-
-    def visit(self, rx, dir, files):
-        if os.path.basename(dir) != self.dirname:
-            # Allow tests/ftests module rather than package.
-            modfname = self.dirname + '.py'
-            if modfname in files:
-                path = os.path.join(dir, modfname)
-                if match(rx, path):
-                    self.files.append(path)
-                    return
-            return
-        # ignore tests that aren't in packages
-        if "__init__.py" not in files:
-            if files in self.EMPTY_FILE_LISTS:
-                return
-            print "not a package", dir
-            return
-
-        # Put matching files in matches.  If matches is non-empty,
-        # then make sure that the package is importable.
-        matches = []
-        for file in files:
-            if file.startswith('test') and os.path.splitext(file)[-1] == '.py':
-                path = os.path.join(dir, file)
-                if match(rx, path):
-                    matches.append(path)
-
-        # ignore tests when the package can't be imported, possibly due to
-        # dependency failures.
-        pkg = dir[self._plen:].replace(os.sep, '.')
-        try:
-            __import__(pkg)
-        # We specifically do not want to catch ImportError since that's useful
-        # information to know when running the tests.
-        except RuntimeError, e:
-            if VERBOSE:
-                print "skipping %s because: %s" % (pkg, e)
-            return
-        else:
-            self.files.extend(matches)
-
-    def module_from_path(self, path):
-        """Return the Python package name indicated by the filesystem path."""
-        assert path.endswith(".py")
-        path = path[self._plen:-3]
-        mod = path.replace(os.sep, ".")
-        return mod
-
-def walk_with_symlinks(top, func, arg):
-    """Like os.path.walk, but follows symlinks on POSIX systems.
-
-    This could theoreticaly result in an infinite loop, if you create symlink
-    cycles in your Zope sandbox, so don't do that.
-    """
-    try:
-        names = os.listdir(top)
-    except os.error:
-        return
-    exceptions = ('.', '..', '{arch}', '.arch-ids')
-    names = [name for name in names
-             if name not in exceptions
-             if not name.startswith(',,')]
-    func(arg, top, names)
-    for name in names:
-        name = os.path.join(top, name)
-        if os.path.isdir(name):
-            walk_with_symlinks(name, func, arg)
-
-def find_test_dir(dir):
-    if os.path.exists(dir):
-        return dir
-    d = os.path.join(pathinit.libdir, dir)
-    if os.path.exists(d):
-        if os.path.isdir(d):
-            return d
-        raise ValueError("%s does not exist and %s is not a directory"
-                         % (dir, d))
-    raise ValueError("%s does not exist!" % dir)
-
-def find_tests(rx):
-    global finder
-    finder = TestFileFinder(pathinit.libdir)
-
-    if TEST_DIRS:
-        for d in TEST_DIRS:
-            d = find_test_dir(d)
-            walk_with_symlinks(d, finder.visit, rx)
-    else:
-        walk_with_symlinks(pathinit.libdir, finder.visit, rx)
-    return finder.files
-
-def package_import(modname):
-    __import__(modname)
-    return sys.modules[modname]
-
-class PseudoTestCase(object):
-    """Minimal test case objects to create error reports.
-
-    If test.py finds something that looks like it should be a test but
-    can't load it or find its test suite, it will report an error
-    using a PseudoTestCase.
-    """
-
-    def __init__(self, name, descr=None):
-        self.name = name
-        self.descr = descr
-
-    def shortDescription(self):
-        return self.descr
-
-    def __str__(self):
-        return "Invalid Test (%s)" % self.name
-
-def get_suite(file, result=None):
-    modname = finder.module_from_path(file)
-    try:
-        mod = package_import(modname)
-        return mod.test_suite()
-    except:
-        if result is not None:
-            result.addError(PseudoTestCase(modname), sys.exc_info())
-            return None
-        raise
-
-def filter_testcases(s, rx):
-    new = unittest.TestSuite()
-    for test in s._tests:
-        # See if the levels match
-        dolevel = (LEVEL == 0) or LEVEL >= getattr(test, "level", 0)
-        if not dolevel:
-            continue
-        if isinstance(test, unittest.TestCase):
-            name = test.id() # Full test name: package.module.class.method
-            name = name[1 + name.rfind("."):] # extract method name
-            if not rx or match(rx, name):
-                new.addTest(test)
-        else:
-            filtered = filter_testcases(test, rx)
-            if filtered:
-                new.addTest(filtered)
-    return new
-
-def gui_runner(files, test_filter):
-    if BUILD_INPLACE:
-        utildir = os.path.join(os.getcwd(), "utilities")
-    else:
-        utildir = os.path.join(os.getcwd(), "..", "utilities")
-    sys.path.append(utildir)
-    import unittestgui
-    suites = []
-    for file in files:
-        suites.append(finder.module_from_path(file) + ".test_suite")
-
-    suites = ", ".join(suites)
-    minimal = (GUI == "minimal")
-    unittestgui.main(suites, minimal)
-
-class TrackRefs(object):
-    """Object to track reference counts across test runs."""
-
-    def __init__(self):
-        self.type2count = {}
-        self.type2all = {}
-
-    def update(self):
-        obs = sys.getobjects(0)
-        type2count = {}
-        type2all = {}
-        for o in obs:
-            all = sys.getrefcount(o)
-
-            if type(o) is str and o == '<dummy key>':
-                # avoid dictionary madness
-                continue
-            t = type(o)
-            if t in type2count:
-                type2count[t] += 1
-                type2all[t] += all
-            else:
-                type2count[t] = 1
-                type2all[t] = all
-
-        ct = [(type2count[t] - self.type2count.get(t, 0),
-               type2all[t] - self.type2all.get(t, 0),
-               t)
-              for t in type2count.iterkeys()]
-        ct.sort()
-        ct.reverse()
-        printed = False
-        for delta1, delta2, t in ct:
-            if delta1 or delta2:
-                if not printed:
-                    print "%-55s %8s %8s" % ('', 'insts', 'refs')
-                    printed = True
-                print "%-55s %8d %8d" % (t, delta1, delta2)
-
-        self.type2count = type2count
-        self.type2all = type2all
-
-def print_doctest_location(err):
-    # This mimicks pdb's output, which gives way cool results in emacs :)
-    filename = err.test.filename
-    if filename.endswith('.pyc'):
-        filename = filename[:-1]
-    print "> %s(%s)_()" % (filename, err.test.lineno+err.example.lineno+1)
-
-def post_mortem(exc_info):
-    from zope.testing import doctest
-    err = exc_info[1]
-    if isinstance(err, (doctest.UnexpectedException, doctest.DocTestFailure)):
-
-        if isinstance(err, doctest.UnexpectedException):
-            exc_info = err.exc_info
-
-            # Print out location info if the error was in a doctest
-            if exc_info[2].tb_frame.f_code.co_filename == '<string>':
-                print_doctest_location(err)
-            
-        else:
-            print_doctest_location(err)
-            # Hm, we have a DocTestFailure exception.  We need to
-            # generate our own traceback
-            try:
-                exec ('raise ValueError'
-                      '("Expected and actual output are different")'
-                      ) in err.test.globs
-            except:
-                exc_info = sys.exc_info()
-        
-    print "%s:" % (exc_info[0], )
-    print exc_info[1]
-    pdb.post_mortem(exc_info[2])
-    sys.exit()
-
-def run_debug(test_or_suite, verbosity):
-    if isinstance(test_or_suite, unittest.TestCase):
-        # test
-        if verbosity > 1:
-            print test_or_suite
-        elif verbosity > 0:
-            print '.',
-
-        try:
-            test_or_suite.debug()
-        except:
-            if DEBUGGER:
-                post_mortem(sys.exc_info())
-            raise
-        return 1
-
-    else:
-        r = 0
-        for t in test_or_suite._tests: # Ick _tests
-            r += run_debug(t, verbosity)
-        return r
-            
-def runner(files, test_filter, debug):
-
-    if DEBUG:
-        runner = result = None 
-    else:
-        runner = ImmediateTestRunner(verbosity=VERBOSE,
-                                     progress=PROGRESS, profile=PROFILE,
-                                     descriptions=False)
-        result = runner.result
-
-    suite = unittest.TestSuite()
-    for file in files:
-        try:
-            s = get_suite(file, result)
-        except:
-            if DEBUGGER:
-                post_mortem(sys.exc_info())
-            raise
-            
-        # See if the levels match
-        dolevel = (LEVEL == 0) or LEVEL >= getattr(s, "level", 0)
-        if s is not None and dolevel:
-            s = filter_testcases(s, test_filter)
-            suite.addTest(s)
-
-    if DEBUG:
-        print "Ran %s tests in debug mode" % run_debug(suite, VERBOSE)
-        return 0
-
-    r = runner.run(suite)
-    if TIMESFN:
-        r.print_times(open(TIMESFN, "w"))
-        if VERBOSE:
-            print "Wrote timing data to", TIMESFN
-    if TIMETESTS:
-        r.print_times(sys.stdout, TIMETESTS)
-    numbad = len(result.failures) + len(result.errors)
-    return numbad
-
-def remove_stale_bytecode(arg, dirname, names):
-    names = map(os.path.normcase, names)
-    for name in names:
-        if name.endswith(".pyc") or name.endswith(".pyo"):
-            srcname = name[:-1]
-            if srcname not in names:
-                fullname = os.path.join(dirname, name)
-                print "Removing stale bytecode file", fullname
-                os.unlink(fullname)
-
-def main(module_filter, test_filter, libdir):
-    if not KEEP_STALE_BYTECODE:
-        os.path.walk(os.curdir, remove_stale_bytecode, None)
-
-    configure_logging()
-
-    # Initialize the path and cwd
-    global pathinit
-    pathinit = PathInit(BUILD, BUILD_INPLACE, libdir)
-
-    files = find_tests(module_filter)
-    if not files:
-        print ("No %s tests to be run."
-               % (functional and "functional" or "unit"))
-        return
-    files.sort()
-
-    # Make sure functional tests find ftesting.zcml
-    if functional:
-        config_file = FTESTING
-        if not pathinit.inplace:
-            # We chdired into build, so ftesting.zcml is in the
-            # parent directory
-            config_file = os.path.join('..', FTESTING)
-        print "Parsing %s" % config_file
-        from zope.app.tests.functional import FunctionalTestSetup
-        FunctionalTestSetup(config_file)
-
-    numbad = 0
-    if GUI:
-        gui_runner(files, test_filter)
-    elif LOOP:
-        if REFCOUNT:
-            rc = sys.gettotalrefcount()
-            track = TrackRefs()
-
-        n = LOOP
-        i = 1
-        while i <= n:
-            print
-            print "Run %s:" % i
-            i += 1;
-            numbad = runner(files, test_filter, DEBUG)
-            gc.collect()
-            if gc.garbage:
-                print "GARBAGE:", len(gc.garbage), gc.garbage
-                return numbad
-
-            if REFCOUNT:
-                prev = rc
-                rc = sys.gettotalrefcount()
-                print "totalrefcount=%-8d change=%-6d" % (rc, rc - prev)
-                track.update()
-    else:
-        numbad = runner(files, test_filter, DEBUG)
-
-    os.chdir(pathinit.org_cwd)
-    return numbad
-
-
-def configure_logging():
-    """Initialize the logging module."""
-    import logging.config
-
-    # Get the log.ini file from the current directory instead of possibly
-    # buried in the build directory.  XXX This isn't perfect because if
-    # log.ini specifies a log file, it'll be relative to the build directory.
-    # Hmm...
-    logini = os.path.abspath("log.ini")
-
-    if os.path.exists(logini):
-        logging.config.fileConfig(logini)
-    else:
-        # If there's no log.ini, cause the logging package to be
-        # silent during testing.
-        root = logging.getLogger()
-        root.addHandler(NullHandler())
-        logging.basicConfig()
-
-    if os.environ.has_key("LOGGING"):
-        level = int(os.environ["LOGGING"])
-        logging.getLogger().setLevel(level)
-
-
-class NullHandler(logging.Handler):
-    """Logging handler that drops everything on the floor.
-
-    We require silence in the test environment.  Hush.
-    """
-
-    def emit(self, record):
-        pass
-
-
-def process_args(argv=None):
-    import getopt
-    global MODULE_FILTER
-    global TEST_FILTER
-    global VERBOSE
-    global LOOP
-    global GUI
-    global TRACE
-    global REFCOUNT
-    global DEBUG
-    global DEBUGGER
-    global BUILD
-    global LEVEL
-    global LIBDIR
-    global TIMESFN
-    global TIMETESTS
-    global PROGRESS
-    global BUILD_INPLACE
-    global KEEP_STALE_BYTECODE
-    global TEST_DIRS
-    global PROFILE
-    global GC_THRESHOLD
-    global GC_FLAGS
-    global RUN_UNIT
-    global RUN_FUNCTIONAL
-    global PYCHECKER
-    global REPORT_ONLY_FIRST_DOCTEST_FAILURE
-
-    if argv is None:
-        argv = sys.argv
-
-    MODULE_FILTERS = []
-    TEST_FILTERS = []
-    VERBOSE = 0
-    LOOP = 0
-    GUI = False
-    TRACE = False
-    REFCOUNT = False
-    DEBUG = False # Don't collect test results; simply let tests crash
-    DEBUGGER = False
-    BUILD = False
-    BUILD_INPLACE = False
-    GC_THRESHOLD = None
-    gcdebug = 0
-    GC_FLAGS = []
-    LEVEL = 1
-    LIBDIR = None
-    PROGRESS = False
-    TIMESFN = None
-    TIMETESTS = 0
-    KEEP_STALE_BYTECODE = 0
-    RUN_UNIT = True
-    RUN_FUNCTIONAL = True
-    TEST_DIRS = []
-    PROFILE = False
-    PYCHECKER = False
-    REPORT_ONLY_FIRST_DOCTEST_FAILURE = False
-    config_filename = 'test.config'
-
-    # import the config file
-    if os.path.isfile(config_filename):
-        print 'Configuration file found.'
-        execfile(config_filename, globals())
-
-
-    try:
-        opts, args = getopt.getopt(argv[1:],
-                                   "a:bBcdDfFg:G:hkl:LmMPprs:tTuUvN:1",
-                                   ["all", "help", "libdir=", "times=",
-                                    "keepbytecode", "dir=", "build",
-                                    "build-inplace",
-                                    "at-level=",
-                                    "pychecker", "debug", "pdebug",
-                                    "gc-threshold=", "gc-option=",
-                                    "loop", "gui", "minimal-gui",
-                                    "test=", "module=",
-                                    "profile", "progress", "refcount", "trace",
-                                    "top-fifty", "verbose", "repeat=",
-                                    "report-only-first-doctest-failure",
-                                    ])
-    # fixme: add the long names
-    # fixme: add the extra documentation
-    # fixme: test for functional first!
-    except getopt.error, msg:
-        print msg
-        print "Try `python %s -h' for more information." % argv[0]
-        sys.exit(2)
-
-    for k, v in opts:
-        if k in ("-a", "--at-level"):
-            LEVEL = int(v)
-        elif k == "--all":
-            LEVEL = 0
-            os.environ["COMPLAIN_IF_TESTS_MISSED"]='1'
-        elif k in ("-b", "--build"):
-            BUILD = True
-        elif k in ("-B", "--build-inplace"):
-            BUILD = BUILD_INPLACE = True
-        elif k in("-c", "--pychecker"):
-            PYCHECKER = True
-        elif k in ("-d", "--debug"):
-            DEBUG = True
-        elif k in ("-D", "--pdebug"):
-            DEBUG = True
-            DEBUGGER = True
-        elif k in ("-f", "--skip-unit"):
-            RUN_UNIT = False
-        elif k in ("-u", "--skip-functional"):
-            RUN_FUNCTIONAL = False
-        elif k == "-F":
-            message = 'Unit plus functional is the default behaviour.'
-            warnings.warn(message, DeprecationWarning)
-            RUN_UNIT = True
-            RUN_FUNCTIONAL = True
-        elif k in ("-h", "--help"):
-            print __doc__
-            sys.exit(0)
-        elif k in ("-g", "--gc-threshold"):
-            GC_THRESHOLD = int(v)
-        elif k in ("-G", "--gc-option"):
-            if not v.startswith("DEBUG_"):
-                print "-G argument must be DEBUG_ flag, not", repr(v)
-                sys.exit(1)
-            GC_FLAGS.append(v)
-        elif k in ('-k', '--keepbytecode'):
-            KEEP_STALE_BYTECODE = 1
-        elif k in ('-l', '--libdir'):
-            LIBDIR = v
-        elif k in ("-L", "--loop"):
-            LOOP = 1000000000
-        elif k in ("-N", "--repeat"):
-            LOOP = int(v)
-        elif k == "-m":
-            GUI = "minimal"
-            msg = "Use -M or --minimal-gui instead of -m."
-            warnings.warn(msg, DeprecationWarning)
-        elif k in ("-M", "--minimal-gui"):
-            GUI = "minimal"
-        elif k in ("-P", "--profile"):
-            PROFILE = True
-        elif k in ("-p", "--progress"):
-            PROGRESS = True
-        elif k in ("-r", "--refcount"):
-                REFCOUNT = True
-        elif k in ("-T", "--trace"):
-            TRACE = True
-        elif k in ("-t", "--top-fifty"):
-            if not TIMETESTS:
-                TIMETESTS = 50
-        elif k in ("-U", "--gui"):
-            GUI = 1
-        elif k in ("-1", "--report-only-first-doctest-failure"):
-            REPORT_ONLY_FIRST_DOCTEST_FAILURE = True
-        elif k in ("-v", "--verbose"):
-            VERBOSE += 1
-        elif k == "--times":
-            try:
-                TIMETESTS = int(v)
-            except ValueError:
-                # must be a filename to write
-                TIMESFN = v
-        elif k in ('-s', '--dir'):
-            TEST_DIRS.append(v)
-        elif k == "--test":
-            TEST_FILTERS.append(v)
-        elif k == "--module":
-            MODULE_FILTERS.append(v)
-
-    if PYCHECKER:
-        # make sure you have a recent version of pychecker
-        if not os.environ.get("PYCHECKER"):
-            os.environ["PYCHECKER"] = "-q"
-        import pychecker.checker
-
-    if REFCOUNT and not hasattr(sys, "gettotalrefcount"):
-        print "-r ignored, because it needs a debug build of Python"
-        REFCOUNT = False
-
-    if sys.version_info < ( 2,3,4 ):
-        print """\
-        ERROR: Your python version is not supported by Zope3.
-        Zope3 needs Python 2.3.4 or greater. You are running:""" + sys.version
-        sys.exit(1)
-
-    if REPORT_ONLY_FIRST_DOCTEST_FAILURE:
-        import zope.testing.doctest
-        zope.testing.doctest.set_unittest_reportflags(
-            zope.testing.doctest.REPORT_ONLY_FIRST_FAILURE)
-        import doctest
-        if hasattr(doctest, 'REPORT_ONLY_FIRST_FAILURE'):
-            doctest.set_unittest_reportflags(doctest.REPORT_ONLY_FIRST_FAILURE)
-
-    if GC_THRESHOLD is not None:
-        if GC_THRESHOLD == 0:
-            gc.disable()
-            print "gc disabled"
-        else:
-            gc.set_threshold(GC_THRESHOLD)
-            print "gc threshold:", gc.get_threshold()
-
-    if GC_FLAGS:
-        val = 0
-        for flag in GC_FLAGS:
-            v = getattr(gc, flag, None)
-            if v is None:
-                print "Unknown gc flag", repr(flag)
-                print gc.set_debug.__doc__
-                sys.exit(1)
-            val |= v
-        gcdebug |= v
-
-    if gcdebug:
-        gc.set_debug(gcdebug)
-
-    if BUILD:
-        # Python 2.3 is more sane in its non -q output
-        if sys.hexversion >= 0x02030000:
-            qflag = ""
-        else:
-            qflag = "-q"
-        cmd = sys.executable + " setup.py " + qflag + " build"
-        if BUILD_INPLACE:
-            cmd += "_ext -i"
-        if VERBOSE:
-            print cmd
-        sts = os.system(cmd)
-        if sts:
-            print "Build failed", hex(sts)
-            sys.exit(1)
-
-    k = []
-    if RUN_UNIT:
-        k.append(False)
-    if RUN_FUNCTIONAL:
-        k.append(True)
-
-    global functional
-    numbad = 0
-    for functional in k:
-
-        if VERBOSE:
-            kind = functional and "FUNCTIONAL" or "UNIT"
-            if LEVEL == 0:
-                print "Running %s tests at all levels" % kind
-            else:
-                print "Running %s tests at level %d" % (kind, LEVEL)
-
-# This was to avoid functional tests outside of z3, but this doesn't really
-# work right.
-##         if functional:
-##             try:
-##                 from zope.app.tests.functional import FunctionalTestSetup
-##             except ImportError:
-##                 raise
-##                 print ('Skipping functional tests: could not import '
-##                        'zope.app.tests.functional')
-##                 continue
-
-        # XXX We want to change *visible* warnings into errors.  The next
-        # line changes all warnings into errors, including warnings we
-        # normally never see.  In particular, test_datetime does some
-        # short-integer arithmetic that overflows to long ints, and, by
-        # default, Python doesn't display the overflow warning that can
-        # be enabled when this happens.  The next line turns that into an
-        # error instead.  Guido suggests that a better to get what we're
-        # after is to replace warnings.showwarning() with our own thing
-        # that raises an error.
-        ## warnings.filterwarnings("error")
-        warnings.filterwarnings("ignore", module="logging")
-
-        if args:
-            if len(args) > 1:
-                TEST_FILTERS.extend(args[1:])
-            MODULE_FILTERS.append(args[0])
-        try:
-            if TRACE:
-                # if the trace module is used, then we don't exit with
-                # status if on a false return value from main.
-                coverdir = os.path.join(os.getcwd(), "coverage")
-                import trace
-                ignoremods = ["os", "posixpath", "stat"]
-                tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix],
-                                     ignoremods=ignoremods,
-                                     trace=False, count=True)
-
-                # we don't get the result from main() from runctx()
-                tracer.runctx("main(MODULE_FILTERS, TEST_FILTERS, LIBDIR)",
-                              globals=globals(), locals=vars())
-                r = tracer.results()
-                path = "/tmp/trace.%s" % os.getpid()
-                import cPickle
-                f = open(path, "wb")
-                cPickle.dump(r, f)
-                f.close()
-                print path
-                r.write_results(show_missing=True,
-                                summary=True, coverdir=coverdir)
-            else:
-                bad = main(MODULE_FILTERS, TEST_FILTERS, LIBDIR)
-                if bad:
-                    numbad += bad
-        except ImportError, err:
-            print err
-            print sys.path
-            raise
-
-    if numbad:
-        sys.exit(1)
-
-
-def test_suite():
-    """Return an empty test suite to avoid complaints about this
-    module not having a 'test_suite' attribute."""
-    return unittest.TestSuite()
-
-
-if __name__ == "__main__":
-    process_args()

Deleted: Zope3/branches/srichter-blow-services/src/zope/app/tests/test_dochttp.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/tests/test_dochttp.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/tests/test_dochttp.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1,132 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (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.
-#
-##############################################################################
-"""Test tcpdoc
-
-$Id$
-"""
-import os
-import unittest
-from zope.testing.doctestunit import DocTestSuite
-import zope.app.tests
-from zope.app.tests.dochttp import dochttp
-
-directory = os.path.join(os.path.split(zope.app.tests.__file__)[0], 'recorded')
-
-
-expected = r'''
-
-  >>> print http(r"""
-  ... GET /@@contents.html HTTP/1.1
-  ... """)
-  HTTP/1.1 401 Unauthorized
-  Content-Length: 89
-  Content-Type: text/html;charset=utf-8
-  Www-Authenticate: basic realm=zope
-  <BLANKLINE>
-  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
-        lang="en">
-  <BLANKLINE>
-  ...
-  <BLANKLINE>
-  </html>
-  <BLANKLINE>
-  <BLANKLINE>
-
-
-  >>> print http(r"""
-  ... GET /@@contents.html HTTP/1.1
-  ... Authorization: Basic bWdyOm1ncnB3
-  ... """)
-  HTTP/1.1 200 Ok
-  Content-Length: 89
-  Content-Type: text/html;charset=utf-8
-  <BLANKLINE>
-  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
-        lang="en">
-  <BLANKLINE>
-  ...
-  <BLANKLINE>
-  </html>
-  <BLANKLINE>
-  <BLANKLINE>
-
-
-  >>> print http(r"""
-  ... GET /++etc++site/@@manage HTTP/1.1
-  ... Authorization: Basic bWdyOm1ncnB3
-  ... Referer: http://localhost:8081/
-  ... """)
-  HTTP/1.1 303 See Other
-  Content-Length: 0
-  Content-Type: text/plain;charset=utf-8
-  Location: @@tasks.html
-  <BLANKLINE>
-
-
-  >>> print http(r"""
-  ... GET / HTTP/1.1
-  ... Authorization: Basic bWdyOm1ncnB3
-  ... """)
-  HTTP/1.1 200 Ok
-  Content-Length: 89
-  Content-Type: text/html;charset=utf-8
-  <BLANKLINE>
-  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
-        lang="en">
-  <BLANKLINE>
-  ...
-  <BLANKLINE>
-  </html>
-  <BLANKLINE>
-  <BLANKLINE>
-
-
-  >>> print http(r"""
-  ... GET /++etc++site/@@tasks.html HTTP/1.1
-  ... Authorization: Basic bWdyOm1ncnB3
-  ... Referer: http://localhost:8081/
-  ... """)
-  HTTP/1.1 200 Ok
-  Content-Length: 89
-  Content-Type: text/html;charset=utf-8
-  <BLANKLINE>
-  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
-        lang="en">
-  <BLANKLINE>
-  ...
-  <BLANKLINE>
-  </html>
-  <BLANKLINE>
-  <BLANKLINE>
-'''
-      
-class Test(unittest.TestCase):
-
-    def test_dochttp(self):
-        import sys, StringIO
-        old = sys.stdout
-        sys.stdout = StringIO.StringIO()
-        dochttp(['-p', 'test', directory])
-        got = sys.stdout.getvalue()
-        sys.stdout = old
-        self.assert_(got == expected)
-
-def test_suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(Test))
-    return suite
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')
-

Deleted: Zope3/branches/srichter-blow-services/src/zope/app/tests/test_functional.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/tests/test_functional.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/tests/test_functional.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1,93 +0,0 @@
-##############################################################################
-#
-# 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.
-#
-##############################################################################
-"""Tests for zope.app.tests.functional."""
-
-import StringIO
-import unittest
-
-import zope.app.tests.functional
-
-
-HEADERS = """\
-HTTP/1.1 200 Ok
-Content-Type: text/plain
-"""
-
-BODY = """\
-This is the response body.
-"""
-
-class DocResponseWrapperTestCase(unittest.TestCase):
-
-    def setUp(self):
-        self.body_output = StringIO.StringIO()
-        self.path = "/foo/bar/"
-        self.response = object()
-
-        self.wrapper = zope.app.tests.functional.DocResponseWrapper(
-            self.response, self.body_output, self.path, HEADERS)
-
-    def test__str__(self):
-        self.assertEqual(str(self.wrapper),
-                         HEADERS + "\n")
-        self.body_output.write(BODY)
-        self.assertEqual(str(self.wrapper),
-                         "%s\n\n%s" % (HEADERS, BODY))
-
-    def test_getBody(self):
-        self.assertEqual(self.wrapper.getBody(), "")
-        self.body_output.write(BODY)
-        self.assertEqual(self.wrapper.getBody(), BODY)
-
-    def test_getOutput(self):
-        self.assertEqual(self.wrapper.getOutput(), "")
-        self.body_output.write(BODY)
-        self.assertEqual(self.wrapper.getOutput(), BODY)
-
-class AuthHeaderTestCase(unittest.TestCase):
-
-    def test_auth_encoded(self):
-        auth_header = zope.app.tests.functional.auth_header
-        header = 'Basic Z2xvYmFsbWdyOmdsb2JhbG1ncnB3'
-        self.assertEquals(auth_header(header), header)
-
-    def test_auth_non_encoded(self):
-        auth_header = zope.app.tests.functional.auth_header
-        header = 'Basic globalmgr:globalmgrpw'
-        expected = 'Basic Z2xvYmFsbWdyOmdsb2JhbG1ncnB3'
-        self.assertEquals(auth_header(header), expected)
-
-    def test_auth_non_encoded_empty(self):
-        auth_header = zope.app.tests.functional.auth_header
-        header = 'Basic globalmgr:'
-        expected = 'Basic Z2xvYmFsbWdyOg=='
-        self.assertEquals(auth_header(header), expected)
-        header = 'Basic :pass'
-        expected = 'Basic OnBhc3M='
-        self.assertEquals(auth_header(header), expected)
-
-    def test_auth_non_encoded_colon(self):
-        auth_header = zope.app.tests.functional.auth_header
-        header = 'Basic globalmgr:pass:pass'
-        expected = 'Basic Z2xvYmFsbWdyOnBhc3M6cGFzcw=='
-        self.assertEquals(auth_header(header), expected)
-
-def test_suite():
-    suite = unittest.TestSuite()
-    suite.addTest(unittest.makeSuite(DocResponseWrapperTestCase))
-    suite.addTest(unittest.makeSuite(AuthHeaderTestCase))
-    return suite
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')

Deleted: Zope3/branches/srichter-blow-services/src/zope/app/tests/ztapi.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/tests/ztapi.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/tests/ztapi.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -1,101 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 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.
-#
-##############################################################################
-"""Testing helper functions
-
-$Id$
-"""
-import zope.interface
-from zope.component.interfaces import IDefaultViewName
-from zope.publisher.browser import IBrowserRequest
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.app import zapi
-from zope.app.traversing.interfaces import ITraversable
-
-def provideView(for_, type, providing, name, factory, layer=None):
-    if layer is None:
-        layer = type
-    provideAdapter(for_, providing, factory, name, (layer,))    
-
-def provideMultiView(for_, type, providing, name, factory, layer=None):
-    if layer is None:
-        layer = type
-    provideAdapter(for_[0], providing, factory, name, tuple(for_[1:])+(layer,))
-
-def browserView(for_, name, factory, layer=IDefaultBrowserLayer,
-                providing=zope.interface.Interface):
-    """Define a global browser view
-    """
-    if isinstance(factory, (list, tuple)):
-        raise ValueError("Factory cannot be a list or tuple")
-    provideAdapter(for_, providing, factory, name, (layer,))
-
-def browserViewProviding(for_, factory, providing, layer=IDefaultBrowserLayer):
-    """Define a view providing a particular interface."""
-    if isinstance(factory, (list, tuple)):
-        raise ValueError("Factory cannot be a list or tuple")
-    return browserView(for_, '', factory, layer, providing)
-
-def browserResource(name, factory, layer=IDefaultBrowserLayer,
-                    providing=zope.interface.Interface):
-    """Define a global browser view
-    """
-    if isinstance(factory, (list, tuple)):
-        raise ValueError("Factory cannot be a list or tuple")
-    provideAdapter((layer,), providing, factory, name)
-
-def setDefaultViewName(for_, name, layer=IDefaultBrowserLayer,
-                       type=IBrowserRequest):
-    if layer is None:
-        layer = type
-    s = zapi.getGlobalServices().getService(zapi.servicenames.Adapters)
-    s.register((for_, layer), IDefaultViewName, '', name)
-
-stypes = list, tuple
-def provideAdapter(required, provided, factory, name='', with=()):
-    if isinstance(factory, (list, tuple)):
-        raise ValueError("Factory cannot be a list or tuple")
-    s = zapi.getGlobalServices().getService(zapi.servicenames.Adapters)
-
-    if with:
-        required = (required, ) + tuple(with)
-    elif not isinstance(required, stypes):
-        required = (required,)
-
-    s.register(required, provided, name, factory)
-
-def subscribe(required, provided, factory):
-    s = zapi.getGlobalServices().getService(zapi.servicenames.Adapters)
-    s.subscribe(required, provided, factory)
-
-def handle(required, handler):
-    subscribe(required, None, handler)
-
-def provideUtility(provided, component, name=''):
-    s = zapi.getGlobalServices().getService(zapi.servicenames.Utilities)
-    s.provideUtility(provided, component, name)
-
-def unprovideUtility(provided, name=''):
-    s = zapi.getGlobalServices().getService(zapi.servicenames.Utilities)
-    s.register((), provided, name, None)
-
-def provideNamespaceHandler(name, handler):
-    provideAdapter(None, ITraversable, handler, name=name)
-    provideView(None, None, ITraversable, name, handler)
-
-def provideService(name, service, interface=None):
-    services = zapi.getGlobalServices()
-    if interface is not None:
-        services.defineService(name, interface)
-    services.provideService(name, service)
-    

Modified: Zope3/branches/srichter-blow-services/src/zope/app/traversing/browser/absoluteurl.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/traversing/browser/absoluteurl.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/traversing/browser/absoluteurl.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -16,14 +16,14 @@
 $Id$
 """
 import urllib
+from zope.interface import implements
+from zope.proxy import sameProxiedObjects
+from zope.publisher.browser import IBrowserRequest
 
+import zope.component as capi
 from zope.app.i18n import ZopeMessageIDFactory as _
-from zope.component import getViewProviding, getView
 from zope.app.publisher.browser import BrowserView
 from zope.app.traversing.browser.interfaces import IAbsoluteURL
-from zope.interface import implements
-from zope.proxy import sameProxiedObjects
-from zope.publisher.browser import IBrowserRequest
 
 _insufficientContext = _("There isn't enough context to get URL information. "
                        "This is probably due to a bug in setting up location "
@@ -32,7 +32,7 @@
 _safe = '@+' # Characters that we don't want to have quoted
 
 def absoluteURL(ob, request):
-    return str(getViewProviding(ob, IAbsoluteURL, request))
+    return str(capi.getMultiAdapter((ob, request), IAbsoluteURL))
 
 class AbsoluteURL(BrowserView):
     implements(IAbsoluteURL)
@@ -54,7 +54,8 @@
         if container is None:
             raise TypeError, _insufficientContext
 
-        url = str(getView(container, 'absolute_url', request))
+        url = str(capi.getMultiAdapter((container, request),
+                                       name='absolute_url'))
         name = self._getContextName(context)
         if name is None:
             raise TypeError, _insufficientContext
@@ -82,7 +83,8 @@
                isinstance(context, Exception):
             return ({'name':'', 'url': self.request.getApplicationURL()}, )
 
-        base = tuple(getView(container, 'absolute_url', request).breadcrumbs())
+        base = tuple(capi.getMultiAdapter((container, request),
+                                          name='absolute_url').breadcrumbs())
 
         name = getattr(context, '__name__', None)
         if name is None:

Modified: Zope3/branches/srichter-blow-services/src/zope/app/traversing/browser/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/traversing/browser/tests.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/traversing/browser/tests.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -16,12 +16,13 @@
 $Id$
 """
 from unittest import TestCase, main, makeSuite
+
+from zope.app import zapi
 from zope.app.container.contained import contained
-from zope.app.tests import ztapi
-from zope.app.tests.placelesssetup import PlacelessSetup
+from zope.app.testing import ztapi
+from zope.app.testing.placelesssetup import PlacelessSetup
 from zope.app.traversing.browser.absoluteurl import absoluteURL
 from zope.app.traversing.browser.interfaces import IAbsoluteURL
-from zope.component import getService, getView
 from zope.i18n.interfaces import IUserPreferredCharsets
 from zope.interface import Interface, implements
 from zope.interface.verify import verifyObject
@@ -52,19 +53,19 @@
     def test_interface(self):
         request = TestRequest()
         content = contained(TrivialContent(), Root(), name='a')
-        view = getView(content, 'absolute_url', request)
+        view = zapi.getMultiAdapter((content, request), name='absolute_url')
         
         verifyObject(IAbsoluteURL, view)
 
     def testBadObject(self):
         request = TestRequest()
-        view = getView(42, 'absolute_url', request)
+        view = zapi.getMultiAdapter((42, request), name='absolute_url')
         self.assertRaises(TypeError, view.__str__)
         self.assertRaises(TypeError, absoluteURL, 42, request)
 
     def testNoContext(self):
         request = TestRequest()
-        view = getView(Root(), 'absolute_url', request)
+        view = zapi.getMultiAdapter((Root(), request), name='absolute_url')
         self.assertEqual(str(view), 'http://127.0.0.1')
         self.assertEqual(absoluteURL(Root(), request), 'http://127.0.0.1')
 
@@ -74,7 +75,7 @@
         content = contained(TrivialContent(), Root(), name='a')
         content = contained(TrivialContent(), content, name='b')
         content = contained(TrivialContent(), content, name='c')
-        view = getView(content, 'absolute_url', request)
+        view = zapi.getMultiAdapter((content, request), name='absolute_url')
         self.assertEqual(str(view), 'http://127.0.0.1/a/b/c')
         self.assertEqual(absoluteURL(content, request),
                          'http://127.0.0.1/a/b/c')
@@ -96,7 +97,7 @@
         content = contained(TrivialContent(), root, name=u'\u0442')
         content = contained(TrivialContent(), content, name=u'\u0435')
         content = contained(TrivialContent(), content, name=u'\u0441')
-        view = getView(content, 'absolute_url', request)
+        view = zapi.getMultiAdapter((content, request), name='absolute_url')
         self.assertEqual(str(view),
                          'http://127.0.0.1/%D0%B9/%D1%82/%D0%B5/%D1%81')
         self.assertEqual(view(),
@@ -127,7 +128,7 @@
         content = contained(TrivialContent(), Root(), name='a')
         content = contained(TrivialContent(), content, name='b')
         content = contained(TrivialContent(), content, name='c')
-        view = getView(content, 'absolute_url', request)
+        view = zapi.getMultiAdapter((content, request), name='absolute_url')
         base = 'http://127.0.0.1/++skin++test'
         self.assertEqual(str(view), base + '/a/b/c')
 
@@ -148,7 +149,7 @@
         request._vh_root = content
         content = contained(TrivialContent(), content, name='b')
         content = contained(TrivialContent(), content, name='c')
-        view = getView(content, 'absolute_url', request)
+        view = zapi.getMultiAdapter((content, request), name='absolute_url')
         self.assertEqual(str(view), 'http://127.0.0.1/b/c')
 
         breadcrumbs = view.breadcrumbs()
@@ -166,7 +167,7 @@
         request._vh_root = content
         content = contained(TrivialContent(), content, name='b')
         content = contained(TrivialContent(), content, name='c')
-        view = getView(content, 'absolute_url', request)
+        view = zapi.getMultiAdapter((content, request), name='absolute_url')
         self.assertEqual(str(view), 'http://127.0.0.1/b/c')
 
         breadcrumbs = view.breadcrumbs()
@@ -185,7 +186,7 @@
         content = contained(TrivialContent(), content, name='a')
         content = contained(TrivialContent(), content, name='b')
         content = contained(TrivialContent(), content, name='c')
-        view = getView(content, 'absolute_url', request)
+        view = zapi.getMultiAdapter((content, request), name='absolute_url')
         self.assertEqual(str(view), 'http://127.0.0.1/a/b/c')
 
         breadcrumbs = view.breadcrumbs()

Modified: Zope3/branches/srichter-blow-services/src/zope/app/traversing/namespace.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/traversing/namespace.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/traversing/namespace.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -17,16 +17,16 @@
 """
 import re
 
+import zope.component as capi
+import zope.interface
 from zope.component.exceptions import ComponentLookupError
-import zope.interface
 from zope.interface import providedBy, directlyProvides, directlyProvidedBy
-from zope import component
-from zope.app.traversing.interfaces import TraversalError
 from zope.publisher.interfaces.browser import ISkin
 from zope.security.proxy import removeSecurityProxy
 
 from zope.app.publisher.browser import applySkin
 from zope.app.traversing.interfaces import ITraversable, IPathAdapter
+from zope.app.traversing.interfaces import TraversalError
 
 # BBB Backward Compatibility
 from zope.exceptions import NotFoundError
@@ -81,7 +81,7 @@
 
        We'll get the same thing if we provide a request:
 
-         >>> from zope.publisher.browser import TestRequest
+       >>> from zope.publisher.browser import TestRequest
          >>> request = TestRequest()
          >>> namespaceLookup('foo', 'bar', C(), request)
          Traceback (most recent call last):
@@ -104,10 +104,10 @@
        """
 
     if request is not None:
-        traverser = component.queryView(object, ns, request,
-                                        providing=ITraversable)
+        traverser = capi.queryMultiAdapter((object, request), 
+                                           ITraversable, ns)
     else:
-        traverser = component.queryAdapter(object, ITraversable, ns)
+        traverser = capi.queryAdapter(object, ITraversable, ns)
 
     if traverser is None:
         raise TraversalError("++%s++%s" % (ns, name))
@@ -167,7 +167,7 @@
     return resource
 
 def queryResource(site, name, request, default=None):
-    resource = component.queryResource(name, request)
+    resource = capi.queryAdapter(request, name=name)
     if resource is None:
         return default
 
@@ -353,7 +353,8 @@
         self.request = request
 
     def traverse(self, name, ignored):
-        view = component.queryView(self.context, name, self.request)
+        view = capi.queryMultiAdapter((self.context, self.request),
+                                           name=name)
         if view is None:
             raise TraversalError(self.context, name)
 
@@ -370,7 +371,7 @@
 
     def traverse(self, name, ignored):
         self.request.shiftNameToApplication()
-        skin = component.getUtility(ISkin, name)
+        skin = capi.getUtility(ISkin, name)
         applySkin(self.request, skin)
         return self.context
 
@@ -447,7 +448,7 @@
              >>> tearDown()
            """
         try:
-            return component.getAdapter(self.context, IPathAdapter, name)
+            return capi.getAdapter(self.context, IPathAdapter, name)
         except:
             raise TraversalError(self.context, name)
 
@@ -527,7 +528,7 @@
                     # TODO: I am not sure this is the best solution.  What
                     # if we want to enable tracebacks when also trying to
                     # debug a different skin?
-                    skin = component.getUtility(ISkin, 'Debug')
+                    skin = capi.getUtility(ISkin, 'Debug')
                     directlyProvides(request, providedBy(request)+skin)
                 else:
                     raise ValueError("Unknown debug flag: %s" % flag)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/traversing/tests/test_presentation.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/traversing/tests/test_presentation.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/traversing/tests/test_presentation.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -16,8 +16,8 @@
 $Id$
 """
 from unittest import TestCase, main, makeSuite
-from zope.app.tests import ztapi
-from zope.app.tests.placelesssetup import PlacelessSetup
+from zope.app.testing import ztapi
+from zope.app.testing.placelesssetup import PlacelessSetup
 from zope.app.traversing.namespace import view, resource
 from zope.interface import Interface, implements
 from zope.publisher.browser import TestRequest

Modified: Zope3/branches/srichter-blow-services/src/zope/app/traversing/tests/test_skin.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/traversing/tests/test_skin.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/traversing/tests/test_skin.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -19,8 +19,8 @@
 from zope.interface import Interface, directlyProvides
 
 from zope.publisher.interfaces.browser import ISkin
-from zope.app.tests import ztapi
-from zope.app.tests.placelesssetup import PlacelessSetup
+from zope.app.testing import ztapi
+from zope.app.testing.placelesssetup import PlacelessSetup
 
 
 class FauxRequest(object):

Modified: Zope3/branches/srichter-blow-services/src/zope/app/traversing/tests/test_traverser.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/traversing/tests/test_traverser.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/traversing/tests/test_traverser.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -17,7 +17,7 @@
 """
 import unittest
 
-from zope.app.tests import ztapi
+from zope.app.testing import ztapi
 from zope.interface import directlyProvides
 from zope.interface.verify import verifyClass
 from zope.interface import implementedBy

Modified: Zope3/branches/srichter-blow-services/src/zope/app/tree/browser/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/tree/browser/tests.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/tree/browser/tests.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -19,7 +19,7 @@
 import unittest
 from zope.publisher.browser import TestRequest
 from zope.app import zapi
-from zope.app.tests import ztapi
+from zope.app.testing import ztapi
 
 from zope.app.tree.utils import TreeStateEncoder
 from zope.app.tree.browser import StatefulTreeView
@@ -55,7 +55,8 @@
 
     def test_cookie_tree_pre_expanded(self):
         request = self.makeRequestWithVar()
-        view = zapi.getView(self.root_obj, 'cookie_tree', request)
+        view = zapi.getMultiAdapter((self.root_obj, request),
+                                    name='cookie_tree')
         cookie_tree = view.cookieTree()
         self.assert_(self.root_node.expanded)
         for node in self.root_node.getFlatNodes():
@@ -63,7 +64,8 @@
 
     def test_cookie_tree_sets_cookie(self):
         request = self.makeRequestWithVar()
-        view = zapi.getView(self.root_obj, 'cookie_tree', request)
+        view = zapi.getMultiAdapter((self.root_obj, request),
+                                    name='cookie_tree')
         cookie_tree = view.cookieTree()
         self.failIf(request.response.getCookie(view.request_variable) is None)
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/utility/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/utility/tests.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/utility/tests.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -260,6 +260,9 @@
         unittest.makeSuite(TestUtilityService),
         unittest.makeSuite(TestLocalUtilityDirective),
         DocTestSuite('zope.app.utility.metaconfigure'),
+        DocTestSuite('zope.app.utility.utility',
+                     setUp=setup.placelessSetUp,
+                     tearDown=setup.placelessTearDown),
         DocTestSuite('zope.app.utility.vocabulary',
                      setUp=setup.placelessSetUp,
                      tearDown=setup.placelessTearDown)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/utility/utility.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/utility/utility.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/utility/utility.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -17,16 +17,18 @@
 $Id$
 """
 from persistent.interfaces import IPersistent
+import zope.interface
+import zope.interface.adapter
+from zope.component.utility import UtilityService, GlobalUtilityService
+from zope.security.proxy import removeSecurityProxy
+
+import zope.app.site.interfaces
+from zope.app import zapi
 from zope.app.adapter.adapter import LocalAdapterService
-from zope.app import zapi
+from zope.app.component.localservice import queryNextService
 from zope.app.registration.registration import ComponentRegistration
 from zope.app.utility.interfaces import ILocalUtilityService
 from zope.app.utility.interfaces import IUtilityRegistration
-from zope.component.utility import UtilityService
-from zope.security.proxy import removeSecurityProxy
-import zope.app.site.interfaces
-import zope.interface
-import zope.interface.adapter
 
 class LocalUtilityService(UtilityService, LocalAdapterService):
     """Local Utility Service
@@ -122,3 +124,140 @@
         # permission; it needs the interface to create a security
         # proxy for the interface with the given permission.
         return self.interface
+
+
+
+_marker = object()
+
+def getNextUtility(context, interface, name=''):
+    """Get the next available utility.
+
+    If no utility was found, a `ComponentLookupError` is raised.
+    """
+    util = queryNextUtility(context, interface, name, _marker)
+    if util is _marker:
+        raise ComponentLookupError, \
+              "No more utilities for %s, '%s' have been found." %(interface,
+                                                                  name)
+    return util
+
+
+def queryNextUtility(context, interface, name='', default=None):
+    """Query for the next available utility.
+
+    Find the next available utility providing `interface` and having the
+    specified name. If no utility was found, return the specified `default`
+    value.
+
+    It is very important that this method really finds the next utility and
+    does not abort, if the utility was not found in the next utility service.
+
+    Let's start out by declaring a utility interface and an implementation:
+
+      >>> from zope.interface import Interface, implements
+      >>> class IAnyUtility(Interface):
+      ...     pass
+      
+      >>> class AnyUtility(object):
+      ...     implements(IAnyUtility)
+      ...     def __init__(self, id):
+      ...         self.id = id
+      
+      >>> any1 = AnyUtility(1)
+      >>> any1next = AnyUtility(2)
+
+    Now that we have the utilities, let's register them:
+
+      >>> testingNextUtility(any1, any1next, IAnyUtility)
+
+    The next utility of `any1` ahould be `any1next`:
+
+      >>> queryNextUtility(any1, IAnyUtility) is any1next
+      True
+
+    But `any1next` does not have a next utility, so the default is returned:
+
+      >>> queryNextUtility(any1next, IAnyUtility) is None
+      True
+
+    """    
+    util = _marker
+    while util is _marker:
+        utilservice = queryNextService(context, zapi.servicenames.Utilities)
+        if utilservice is None:
+            return default
+        util = utilservice.queryUtility(interface, name, _marker)
+        context = utilservice
+        
+    return util
+
+
+def testingNextUtility(utility, nextutility, interface, name='',
+                       service=None, nextservice=None):
+    """Provide a next utility for testing.
+
+    Since utilities must be registered in services, we really provide a next
+    utility service in which we place the next utility. If you do not pass in
+    any services, they will be created for you.
+
+    For a simple usage of this function, see the doc test of
+    `queryNextUtility()`. Here is a demonstration that passes in the services
+    directly and ensures that the `__parent__` attributes are set correctly.
+
+    First, we need to create a utility interface and implementation:
+
+      >>> from zope.interface import Interface, implements
+      >>> class IAnyUtility(Interface):
+      ...     pass
+      
+      >>> class AnyUtility(object):
+      ...     implements(IAnyUtility)
+      ...     def __init__(self, id):
+      ...         self.id = id
+      
+      >>> any1 = AnyUtility(1)
+      >>> any1next = AnyUtility(2)
+
+    Now we create a special utility service that can have a location:
+
+      >>> UtilityService = type('UtilityService', (GlobalUtilityService,),
+      ...                       {'__parent__': None})
+
+    Let's now create one utility service
+
+      >>> utils = UtilityService()
+
+    and pass it in as the original utility service to the function:
+
+      >>> testingNextUtility(any1, any1next, IAnyUtility, service=utils)
+      >>> any1.__parent__ is utils
+      True
+      >>> utilsnext = any1next.__parent__
+      >>> utils.__parent__.next.data['Utilities'] is utilsnext
+      True
+
+    or if we pass the current and the next utility service:
+
+      >>> utils = UtilityService()
+      >>> utilsnext = UtilityService()
+      >>> testingNextUtility(any1, any1next, IAnyUtility,
+      ...                    service=utils, nextservice=utilsnext)
+      >>> any1.__parent__ is utils
+      True
+      >>> any1next.__parent__ is utilsnext
+      True
+    
+    """
+    UtilityService = type('UtilityService', (GlobalUtilityService,),
+                          {'__parent__': None})
+    if service is None:
+        service = UtilityService()
+    if nextservice is None:
+        nextservice = UtilityService()
+    from zope.app.component.localservice import testingNextService
+    testingNextService(service, nextservice, zapi.servicenames.Utilities)
+
+    service.provideUtility(interface, utility, name)
+    utility.__parent__ = service
+    nextservice.provideUtility(interface, nextutility, name)
+    nextutility.__parent__ = nextservice

Modified: Zope3/branches/srichter-blow-services/src/zope/app/workflow/tests/workflowsetup.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/workflow/tests/workflowsetup.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/workflow/tests/workflowsetup.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -15,17 +15,12 @@
 
 $Id$
 """
-from zope.interface import implements
-from zope.component.interfaces import IUtilityService
-
 from zope.app import zapi
 from zope.app.annotation.interfaces import IAttributeAnnotatable
-from zope.app.security.interfaces import IAuthenticationService
-from zope.app.security.principalregistry import principalRegistry
-from zope.app.servicenames import Authentication, Utilities
+from zope.app.servicenames import Utilities
 from zope.app.site.tests.placefulsetup import PlacefulSetup
-from zope.app.utility import LocalUtilityService
 from zope.app.tests import setup
+from zope.app.utility import LocalUtilityService
 
 
 class WorkflowSetup(PlacefulSetup):
@@ -44,9 +39,3 @@
 
         self.default1 = zapi.traverse(self.sm1, "default")
         self.cm1 = self.default1.getRegistrationManager()
-
-
-    def setupAuthService(self):
-        self.root_sm.defineService(Authentication, IAuthenticationService)
-        self.root_sm.provideService(Authentication, principalRegistry)
-        return zapi.getService(Authentication, self.rootFolder)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/zapi/README.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/zapi/README.txt	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/zapi/README.txt	2004-12-21 16:57:29 UTC (rev 28670)
@@ -14,21 +14,23 @@
 service is defined, a ComponentLookupError is raised:
 
   >>> from zope.app import zapi
-  >>> zapi.principals()
+  >>> zapi.principals() #doctest: +NORMALIZE_WHITESPACE
   Traceback (most recent call last):
   ...
-  ComponentLookupError: 'Authentication'
+  ComponentLookupError:
+  (<InterfaceClass zope.app.security.interfaces.IAuthenticationUtility>, '')
 
+
 But if we provide an authentication service:
 
   >>> import zope.interface
-  >>> from zope.app.security.interfaces import IAuthenticationService
-  >>> class FakeAuthenticationService:
-  ...     zope.interface.implements(IAuthenticationService)
-  >>> fake = FakeAuthenticationService()
+  >>> from zope.app.security.interfaces import IAuthenticationUtility
+  >>> class FakeAuthenticationUtility:
+  ...     zope.interface.implements(IAuthenticationUtility)
+  >>> fake = FakeAuthenticationUtility()
   
   >>> from zope.app.tests import ztapi
-  >>> ztapi.provideService(zapi.servicenames.Authentication, fake)
+  >>> ztapi.provideUtility(IAuthenticationUtility, fake)
 
 Then we should be able to get the service back when we ask for the
 principals: 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/zapi/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/zapi/__init__.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/zapi/__init__.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -17,7 +17,6 @@
 
 $Id$
 """
-
 from interfaces import IZAPI
 from zope.interface import moduleProvides
 
@@ -38,5 +37,6 @@
 name = getName
 
 def principals():
-    return getServices().getService(servicenames.Authentication)
+    from zope.app.security.interfaces import IAuthenticationUtility
+    return getUtility(IAuthenticationUtility)
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/zapi/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/zapi/tests.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/zapi/tests.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -11,21 +11,17 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""XXX short summary goes here.
+"""ZTAPI Tests
 
 $Id$
 """
 import unittest
 from zope.app.tests import placelesssetup
 from zope.app import zapi
-from zope.app.security.interfaces import IAuthenticationService
 
 
 def setUp(test):
     placelesssetup.setUp()
-    services = zapi.getGlobalServices()
-    services.defineService(zapi.servicenames.Authentication,
-                           IAuthenticationService)
 
 def test_suite():
     from zope.testing import doctest

Modified: Zope3/branches/srichter-blow-services/src/zope/app/zopeappgenerations/evolve1.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/zopeappgenerations/evolve1.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/zopeappgenerations/evolve1.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -21,6 +21,9 @@
 from zope.app.error.interfaces import IErrorReportingService
 from zope.app.error.interfaces import IErrorReportingUtility
 from zope.app.generations.utility import findObjectsProviding
+from zope.app.principalannotation import PrincipalAnnotationUtility
+from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility
+from zope.app.principalannotation.interfaces import IPrincipalAnnotationService
 from zope.app.registration.interfaces import IComponentRegistration
 from zope.app.registration.interfaces import ActiveStatus, UnregisteredStatus
 from zope.app.site.interfaces import ISite, IServiceRegistration
@@ -32,6 +35,10 @@
 def evolve(context):
     """Evolve the ZODB from a Zope X3.0 to a X3.1 compatible format.
 
+    - The Principal Annotation Service was replaced by the Principal
+      Annotation Utility. Thus all service registrations have to be changed to
+      utility registrations. 
+
     - The Error Reporting Service was replaced by the Error Reporting
       Utility. Thus, all service registrations have to be changed to utility
       registrations. 
@@ -42,6 +49,43 @@
     """
     root = getRootFolder(context)
 
+    # Fix up Principal Annotation Service --> Utility 
+    # We do this by simply removing old Principal Annotation Services and their
+    # registrations and then add a new Principal Annotation utility.
+    for site in findObjectsProviding(root, ISite):
+        for reg in findObjectsProviding(site.getSiteManager(),
+                                        IServiceRegistration):
+        
+            if reg.name == 'PrincipalAnnotation':
+                ann = reg.component
+                # Set the registration to unregistered and then delete it
+                reg.status = UnregisteredStatus
+                del zapi.getParent(reg)[zapi.name(reg)]
+                # Get the instance dictionary from the old principal
+                # annotation service and then delete the service
+                props = ann.__dict__
+                name = zapi.name(ann)
+                folder = zapi.getParent(ann)
+                del folder[name]
+
+
+                # Only add a new principal annotation utility, if there is none.
+                utils = [obj for obj in folder.values()
+                         if isinstance(obj, PrincipalAnnotationUtility)]
+                if len(utils) == 0:
+                    # Create the principal annotation utility and set its
+                    # properties
+                    utility = PrincipalAnnotationUtility()
+                    utility.__dict__.update(props)
+                    folder[name] = utility
+                    # Register the utility and set the registration active
+                    reg = UtilityRegistration('', IPrincipalAnnotationUtility,
+                                              utility)
+                    reg_manager = folder.getRegistrationManager() 
+                    key = reg_manager.addRegistration(reg)
+                    reg_manager[key].status = ActiveStatus
+
+
     # Fix up Error Reporting Service --> Utility 
     # We do this by simply removing old Error Reporting Services and their
     # registrations and then add a new error reporting utility.

Modified: Zope3/branches/srichter-blow-services/src/zope/app/zptpage/tests/test_zptpage.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/zptpage/tests/test_zptpage.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/zptpage/tests/test_zptpage.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -22,13 +22,13 @@
 from zope.interface.verify import verifyClass
 from zope.security.interfaces import Forbidden
 
-from zope.app.tests import ztapi
-from zope.component import getView
+from zope.app import zapi
+from zope.app.testing import ztapi
 from zope.publisher.browser import TestRequest
 from zope.app.publisher.browser import BrowserView
 
 # Wow, this is a lot of work. :(
-from zope.app.tests.placelesssetup import PlacelessSetup
+from zope.app.testing.placelesssetup import PlacelessSetup
 from zope.app.traversing.adapters import Traverser, DefaultTraversable
 from zope.app.traversing.interfaces import ITraverser, ITraversable
 from zope.app.traversing.interfaces import IPhysicallyLocatable
@@ -228,7 +228,7 @@
         page.setSource(html, content_type='text/plain')
         request = TestRequest()
 
-        view = getView(page, 'source.html', request)
+        view = zapi.getMultiAdapter((page, request), name='source.html')
 
         self.assertEqual(str(view), html)
         self.assertEqual(view(), html)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/zptpage/textindex/tests.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/zptpage/textindex/tests.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/app/zptpage/textindex/tests.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -17,8 +17,8 @@
 """
 
 from zope.index.text.interfaces import ISearchableText
-from zope.app.tests import ztapi
-from zope.app.tests.placelesssetup import PlacelessSetup
+from zope.app.testing import ztapi
+from zope.app.testing.placelesssetup import PlacelessSetup
 from zope.app.zptpage.interfaces import IZPTPage
 from zope.app.zptpage.textindex.zptpage import SearchableText
 from zope.app.zptpage.zptpage import ZPTPage

Modified: Zope3/branches/srichter-blow-services/src/zope/component/README.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/component/README.txt	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/component/README.txt	2004-12-21 16:57:29 UTC (rev 28670)
@@ -43,8 +43,7 @@
     >>> zope.component.getUtility(IGreeter, 'robert').greet()
     Hello bob
 
-`queryUtility` and `getUtility` differ in how failed lookups are
-handled:
+`queryUtility` and `getUtility` differ in how failed lookups are handled:
 
     >>> zope.component.queryUtility(IGreeter, 'ted')
     >>> zope.component.queryUtility(IGreeter, 'ted', 42)
@@ -56,8 +55,7 @@
     ComponentLookupError: (<InterfaceClass ...IGreeter>, 'ted')
 
 If a component provides only one interface, as in the example above,
-then we can ommit the provided interface from the call to
-`provideUtility`:
+then we can omit the provided interface from the call to `provideUtility`:
 
     >>> ted = Greeter('ted')
     >>> zope.component.provideUtility(ted, name='ted')

Modified: Zope3/branches/srichter-blow-services/src/zope/component/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/component/__init__.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/component/__init__.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -132,25 +132,26 @@
 
     return getSiteManager(context).queryAdapter(object, interface, '', default)
 
-def getAdapter(object, interface, name, context=None):
+def getAdapter(object, interface=Interface, name=u'', context=None):
     adapter = queryAdapter(object, interface, name, None, context)
     if adapter is None:
         raise ComponentLookupError(object, interface)
     return adapter
 
-def queryAdapter(object, interface, name, default=None, context=None):
+def queryAdapter(object, interface=Interface, name=u'', default=None,
+                 context=None):
     if context is None:
         return adapter_hook(interface, object, name, default)
     return getSiteManager(context).queryAdapter(object, interface, name,
                                                 default)
 
-def getMultiAdapter(objects, interface, name=u'', context=None):
+def getMultiAdapter(objects, interface=Interface, name=u'', context=None):
     adapter = queryMultiAdapter(objects, interface, name, context=context)
     if adapter is None:
         raise ComponentLookupError(objects, interface)
     return adapter
 
-def queryMultiAdapter(objects, interface, name=u'', default=None,
+def queryMultiAdapter(objects, interface=Interface, name=u'', default=None,
                       context=None):
     try:
         sitemanager = getSiteManager(context)

Modified: Zope3/branches/srichter-blow-services/src/zope/component/interfaces.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/component/interfaces.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/component/interfaces.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -37,7 +37,25 @@
     and Utiltities. Both are managed by site managers. All other components
     build on top of them.
     """
+    # Site Manager API
 
+    def getGlobalSiteManager():
+        """Return the global site manager.
+
+        This function should never fail and always return an object that
+        provides `IGlobalSiteManager`.
+        """
+
+    def getSiteManager(context=None):
+        """Get the nearest site manager in the given context.
+
+        If `context` is `None`, return the global site manager.
+
+        If the `context` is not `None`, it is expected that an adapter from
+        the `context` to `ISiteManager` can be found. If no adapter is found,
+        a `ComponentLookupError` is raised.
+        """
+
     # Utility API
 
     def getUtility(interface, name='', context=None):
@@ -72,7 +90,7 @@
 
     # Adapter API
 
-    def getAdapter(object, interface, name, context=''):
+    def getAdapter(object, interface=Interface, name=u'', context=None):
         """Get a named adapter to an interface for an object
 
         Returns an adapter that can adapt object to interface.  If a matching
@@ -107,7 +125,7 @@
         returned.
         """
 
-    def getMultiAdapter(objects, interface, name='', context=None):
+    def getMultiAdapter(objects, interface=Interface, name='', context=None):
         """Look for a multi-adapter to an interface for an objects
 
         Returns a multi-adapter that can adapt objects to interface.  If a
@@ -124,7 +142,8 @@
         named adapter methods with an empty string for a name.
         """
 
-    def queryAdapter(object, interface, name, default=None, context=None):
+    def queryAdapter(object, interface=Interface, name=u'', default=None,
+                     context=None):
         """Look for a named adapter to an interface for an object
 
         Returns an adapter that can adapt object to interface.  If a matching
@@ -159,7 +178,7 @@
         returned.
         """
 
-    def queryMultiAdapter(objects, interface, name='', default=None,
+    def queryMultiAdapter(objects, interface=Interface, name=u'', default=None,
                           context=None):
         """Look for a multi-adapter to an interface for objects
 

Modified: Zope3/branches/srichter-blow-services/src/zope/component/site.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/component/site.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/component/site.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -112,8 +112,9 @@
 
     implements(IGlobalSiteManager)
 
-    def __init__(self):
+    def __init__(self, name=None):
         super(GlobalSiteManager, self).__init__()
+        self.__name__ = None
         self._registrations = {}
 
     def provideAdapter(self, required, provided, name, factory, info=''):
@@ -241,9 +242,13 @@
             else:
                 yield registration
 
+    def __reduce__(self):
+        # Global service managers are pickled as global objects
+        return self.__name__
 
+
 # Global Site Manager Instance
-globalSiteManager = GlobalSiteManager()
+globalSiteManager = GlobalSiteManager('globalSiteManager')
 
 # Register our cleanup with zope.testing.cleanup to make writing unit tests
 # simpler.

Modified: Zope3/branches/srichter-blow-services/src/zope/interface/adapter.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/interface/adapter.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/interface/adapter.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -196,17 +196,18 @@
 
         # Now flatten with mappings to tuples
         for key, v in implied.iteritems():
-            if isinstance(key, tuple) and key[0] == 's':
-                # subscriptions
-                if isinstance(v, dict):
-                    implied[key] = v.items()
-            else:
-                byname = v
-                for name, value in byname.iteritems():
-                    if isinstance(value, dict):
-                        # We have {with -> value}
-                        # convert it to sorted [(with, value]
-                        byname[name] = orderwith(value)
+            if isinstance(key, tuple):
+                if key[0] == 's':
+                    # subscriptions
+                    if isinstance(v, dict):
+                        implied[key] = v.items()
+                else:
+                    byname = v
+                    for name, value in byname.iteritems():
+                        if isinstance(value, dict):
+                            # We have {with -> value}
+                            # convert it to sorted [(with, value]
+                            byname[name] = orderwith(value)
 
         self.get = implied.get
 
@@ -296,9 +297,9 @@
     # Adapter lookup support
     # We have a class here because we want to provide very
     # fast lookup support in C and making this part of the adapter
-    # registry itself would provide problems if someone wanted to
+    # registry itself would provide problems if someone wanted
     # persistent adapter registries, because we want C slots for fast
-    # lookup that would clash with persistence-suppplied slots.
+    # lookup that would clash with persistence-supplied slots.
     # so this class acts a little bit like a lookup adapter for the adapter
     # registry.
 

Modified: Zope3/branches/srichter-blow-services/src/zope/interface/adapter.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/interface/adapter.txt	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/interface/adapter.txt	2004-12-21 16:57:29 UTC (rev 28670)
@@ -244,6 +244,17 @@
   >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
   'C21'
 
+Dict adapters
+-------------
+
+At some point it was impossible to register dictionary-based adapters due a
+bug. Let's make sure this works now:
+
+  >>> adapter = {}
+  >>> registry.register((), IQ, '', adapter)
+  >>> registry.lookup((), IQ, '') is adapter
+  True
+
 Unregistering
 -------------
 
@@ -482,7 +493,7 @@
 
 A handler is a subscriber factory that doesn't produce any normal
 output.  It returns None.  A handler is unlike adapters in that it does
-all of it's work when the factory is called.
+all of its work when the factory is called.
 
 To register a handler, simply provide None as the provided interface::
 

Modified: Zope3/branches/srichter-blow-services/src/zope/publisher/http.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/publisher/http.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/publisher/http.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -884,8 +884,12 @@
         after beginning stream-oriented output.
 
         """
-        self.output(string)
+        if not self._wrote_headers:
+            self.outputHeaders()
+            self._wrote_headers = True
 
+        self._outstream.write(string)
+
     def output(self, data):
         """Output the data to the world. There are a couple of steps we have
         to do:
@@ -909,13 +913,9 @@
             data = self._encode(data)
             self._updateContentLength(data)
 
-        if not self._wrote_headers:
-            self.outputHeaders()
-            self._wrote_headers = True
+        self.write(data)
 
-        self._outstream.write(data)
 
-
     def outputBody(self):
         """Outputs the response body."""
         self.output(self._body)

Modified: Zope3/branches/srichter-blow-services/src/zope/publisher/tests/test_http.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/publisher/tests/test_http.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/publisher/tests/test_http.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -446,6 +446,24 @@
         response.outputBody()
         return self._parseResult(stream.getvalue())
 
+    def testWrite(self):
+        response, stream = self._createResponse()
+        data = 'a'*10
+        # We have to set all the headers ourself
+        response.setHeader('Content-Type', 'text/plain;charset=us-ascii')
+        response.setHeader('Content-Length', str(len(data)))
+
+        # Stream the data
+        for ch in data:
+            response.write(ch)
+
+        headers, body = self._parseResult(stream.getvalue())
+        # Check that the data have been written, and that the header
+        # has been preserved   
+        self.assertEqual(headers['Content-Type'], 'text/plain;charset=us-ascii')
+        self.assertEqual(headers['Content-Length'], str(len(data)))
+        self.assertEqual(body, data)
+
     def testContentLength(self):
         eq = self.failUnlessEqual
 

Modified: Zope3/branches/srichter-blow-services/src/zope/security/untrustedinterpreter.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/security/untrustedinterpreter.txt	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/security/untrustedinterpreter.txt	2004-12-21 16:57:29 UTC (rev 28670)
@@ -197,7 +197,7 @@
 object.  Therefore, the access to the basic object in the first place
 is mediated by the security functions.
 
-Rational for mutable safe objects
+Rationale for mutable safe objects
 *********************************
 
 Some safe objects are not basic. For these objects, we proxy the

Modified: Zope3/branches/srichter-blow-services/src/zope/tales/interfaces.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/tales/interfaces.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/src/zope/tales/interfaces.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -109,7 +109,7 @@
             """
 
         def length():
-            """Return whether the length of the sequence
+            """Return the length of the sequence
 
             Note that this may fail if the TAL iterator was created on a Python
             iterator.

Modified: Zope3/branches/srichter-blow-services/test.py
===================================================================
--- Zope3/branches/srichter-blow-services/test.py	2004-12-21 16:55:26 UTC (rev 28669)
+++ Zope3/branches/srichter-blow-services/test.py	2004-12-21 16:57:29 UTC (rev 28670)
@@ -21,7 +21,7 @@
 here = os.path.dirname(os.path.realpath(__file__))
 sys.path.insert(0, os.path.join(here, 'src'))
 
-import zope.app.tests.test
+import zope.app.testing.test
 
 if __name__ == '__main__':
-    zope.app.tests.test.process_args()
+    zope.app.testing.test.process_args()



More information about the Zope3-Checkins mailing list