[Checkins] SVN: zope.pluggableauth/trunk/src/zope/pluggableauth/ Mass bashing of ZMI-related or totally unrelated components (principal registries).

Souheil CHELFOUH souheil at chelfouh.com
Sat Jan 23 12:52:16 EST 2010


Log message for revision 108409:
  Mass bashing of ZMI-related or totally unrelated components (principal registries).
  A bit of reorganisation. Next time will be to clear the browser folder and to check all the imports.
  zope.app.authentication still uses zope.app.zcmlfiles, zope.app.component and zope.app.container.
  This needs to change too, of course.
  

Changed:
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/configure.zcml
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/ftesting.zcml
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/ftpplugins.py
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/ftpplugins.zcml
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/generic.py
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/groupfolder.py
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/groupfolder.txt
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/groupfolder.zcml
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/httpplugins.py
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/httpplugins.zcml
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/password.py
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/password.zcml
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/placelesssetup.py
  A   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/
  A   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/ftpplugins.py
  A   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/ftpplugins.zcml
  A   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/generic.py
  A   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/httpplugins.py
  A   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/httpplugins.zcml
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/principalfolder.py
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/principalfolder.txt
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/principalfolder.zcml
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/vocabulary.py
  D   zope.pluggableauth/trunk/src/zope/pluggableauth/vocabulary.txt

-=-
Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/configure.zcml
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/configure.zcml	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/configure.zcml	2010-01-23 17:52:16 UTC (rev 108409)
@@ -23,16 +23,6 @@
       />
 
   <utility
-      component=".vocabulary.credentialsPlugins"
-      name="CredentialsPlugins"
-      />
-
-  <utility
-      component=".vocabulary.authenticatorPlugins"
-      name="AuthenticatorPlugins"
-      />
-
-  <utility
       name="No Challenge if Authenticated"
       factory=".generic.NoChallengeCredentialsPlugin"
       provides=".interfaces.ICredentialsPlugin"

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/ftesting.zcml
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/ftesting.zcml	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/ftesting.zcml	2010-01-23 17:52:16 UTC (rev 108409)
@@ -9,10 +9,9 @@
 
   <include package="zope.securitypolicy" file="meta.zcml" />
 
-  <include package="zope.app.zcmlfiles" />
   <include package="zope.formlib" />
   <include package="zope.session" />
-  <include package="zope.app.authentication" />
+  <include package="zope.pluggableauth" />
   <include package="zope.app.securitypolicy" />
   <include package="zope.login" />
 

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/ftpplugins.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/ftpplugins.py	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/ftpplugins.py	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,65 +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.
-#
-##############################################################################
-"""PAS plugins related to FTP
-"""
-__docformat__ = 'restructuredtext'
-
-from zope.interface import implements
-from zope.publisher.interfaces.ftp import IFTPRequest
-
-from zope.app.authentication import interfaces
-
-class FTPCredentialsPlugin(object):
-
-    implements(interfaces.ICredentialsPlugin)
-
-    def extractCredentials(self, request):
-        """Extracts the FTP credentials from a request.
-
-        First we need to create a FTP request that contains some credentials.
-        Note the path is a required in the envirnoment.
-
-          >>> from zope.publisher.ftp import FTPRequest
-          >>> from StringIO import StringIO
-          >>> request = FTPRequest(StringIO(''),
-          ...                      {'credentials': ('bob', '123'),
-          ...                       'path': '/a/b/c'})
-
-        Now we create the plugin and get the credentials.
-
-          >>> plugin = FTPCredentialsPlugin()
-          >>> plugin.extractCredentials(request)
-          {'login': u'bob', 'password': u'123'}
-
-        This only works for FTPRequests.
-
-          >>> from zope.publisher.base import TestRequest
-          >>> print plugin.extractCredentials(TestRequest('/'))
-          None
-
-        """
-        if not IFTPRequest.providedBy(request):
-            return None
-
-        if request._auth:
-            login, password = request._auth
-            return {'login': login.decode('utf-8'),
-                    'password': password.decode('utf-8')}
-        return None
-
-    def challenge(self, request):
-        return False
-
-    def logout(self, request):
-        return False

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/ftpplugins.zcml
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/ftpplugins.zcml	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/ftpplugins.zcml	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,12 +0,0 @@
-<configure
-    xmlns="http://namespaces.zope.org/zope"
-    i18n_domain="zope"
-    >
-
-  <utility
-      name="FTP Credentials"
-      provides=".interfaces.ICredentialsPlugin"
-      factory=".ftpplugins.FTPCredentialsPlugin"
-      />
-
-</configure>

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/generic.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/generic.py	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/generic.py	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,94 +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.
-#
-##############################################################################
-"""Generic PAS Plugins
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-from zope.interface import implements
-from zope.authentication.interfaces import IUnauthenticatedPrincipal
-
-from zope.app.authentication import interfaces
-
-
-class NoChallengeCredentialsPlugin(object):
-    """A plugin that doesn't challenge if the principal is authenticated.
-
-    There are two reasonable ways to handle an unauthorized error for an
-    authenticated principal:
-
-      - Inform the user of the unauthorized error
-
-      - Let the user login with a different set of credentials
-
-    Since either approach is reasonable, we need to give the site manager
-    some way of specifying one of the two policies.
-
-    By default, a user will be challenged for a new set of credentials if
-    unauthorized. A site manager can insert this plugin in the front of the
-    plugin list to prevent that challenge from occurring. This will
-    typically result in an 'Unauthorized' message to the user.
-
-    The 'challenge' behavior of the plugin is simple. To illustrate, we'll
-    create a plugin:
-
-      >>> challenger = NoChallengeCredentialsPlugin()
-
-    and a test request with an authenticated principal:
-
-      >>> from zope.publisher.browser import TestRequest
-      >>> request = TestRequest()
-      >>> IUnauthenticatedPrincipal.providedBy(request.principal)
-      False
-
-    When we challenge using the plugin:
-
-      >>> challenger.challenge(request)
-      True
-
-    we get a value that signals the PAU that this plugin successfully
-    challenged the user (even though it actually did nothing). The PAU
-    will stop trying to challenge and the user will not get a chance to
-    provide different credentials. The result is typically an error message.
-
-    On the other hand, if the user is unauthenticated:
-
-      >>> class Principal(object):
-      ...     implements(IUnauthenticatedPrincipal)
-      >>> request.setPrincipal(Principal())
-      >>> IUnauthenticatedPrincipal.providedBy(request.principal)
-      True
-
-    the plugin challenge will return None:
-
-      >>> print challenger.challenge(request)
-      None
-
-    signaling the PAU that it should try the next plugin for a challenge. If
-    the PAU is configured properly, the user will receive a challenge and be
-    allowed to provide different credentials.
-    """
-    implements(interfaces.ICredentialsPlugin)
-
-    def extractCredentials(self, request):
-        return None
-
-    def challenge(self, request):
-        if not IUnauthenticatedPrincipal.providedBy(request.principal):
-            return True
-        return None
-
-    def logout(self, request):
-        return False
-

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/groupfolder.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/groupfolder.py	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/groupfolder.py	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,363 +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.
-#
-##############################################################################
-"""Zope Groups Folder implementation
-
-$Id$
-
-"""
-import BTrees.OOBTree
-import persistent
-
-from zope import interface, event, schema, component
-from zope.interface import alsoProvides
-from zope.security.interfaces import (
-    IGroup, IGroupAwarePrincipal, IMemberAwareGroup)
-
-from zope.container.btree import BTreeContainer
-import zope.container.constraints
-import zope.container.interfaces
-from zope.app.authentication.i18n import ZopeMessageFactory as _
-import zope.authentication.principal
-from zope.authentication.interfaces import (
-    IAuthentication, IAuthenticatedGroup, IEveryoneGroup)
-from zope.app.authentication import principalfolder, interfaces
-
-
-class IGroupInformation(interface.Interface):
-
-    title = schema.TextLine(
-        title=_("Title"),
-        description=_("Provides a title for the permission."),
-        required=True)
-
-    description = schema.Text(
-        title=_("Description"),
-        description=_("Provides a description for the permission."),
-        required=False)
-
-    principals = schema.List(
-        title=_("Principals"),
-        value_type=schema.Choice(
-            source=zope.authentication.principal.PrincipalSource()),
-        description=_(
-        "List of ids of principals which belong to the group"),
-        required=False)
-
-
-class IGroupFolder(zope.container.interfaces.IContainer):
-
-    zope.container.constraints.contains(IGroupInformation)
-
-    prefix = schema.TextLine(
-        title=_("Group ID prefix"),
-        description=_("Prefix added to IDs of groups in this folder"),
-        readonly=True,
-        )
-
-    def getGroupsForPrincipal(principalid):
-        """Get groups the given principal belongs to"""
-
-    def getPrincipalsForGroup(groupid):
-        """Get principals which belong to the group"""
-
-
-class IGroupContained(zope.container.interfaces.IContained):
-
-    zope.container.constraints.containers(IGroupFolder)
-
-class IGroupSearchCriteria(interface.Interface):
-
-    search = schema.TextLine(
-        title=_("Group Search String"),
-        required=False,
-        missing_value=u'',
-        )
-
-class IGroupPrincipalInfo(interfaces.IPrincipalInfo):
-    members = interface.Attribute('an iterable of members of the group')
-
-class GroupInfo(object):
-    """An implementation of IPrincipalInfo used by the group folder.
-
-    A group info is created with id, title, and description:
-
-      >>> class DemoGroupInformation(object):
-      ...     interface.implements(IGroupInformation)
-      ...     def __init__(self, title, description, principals):
-      ...         self.title = title
-      ...         self.description = description
-      ...         self.principals = principals
-      ...
-      >>> i = DemoGroupInformation(
-      ...     'Managers', 'Taskmasters', ('joe', 'jane'))
-      ...
-      >>> info = GroupInfo('groups.managers', i)
-      >>> info
-      GroupInfo('groups.managers')
-      >>> info.id
-      'groups.managers'
-      >>> info.title
-      'Managers'
-      >>> info.description
-      'Taskmasters'
-      >>> info.members
-      ('joe', 'jane')
-      >>> info.members = ('joe', 'jane', 'jaime')
-      >>> info.members
-      ('joe', 'jane', 'jaime')
-
-    """
-    interface.implements(IGroupPrincipalInfo)
-
-    def __init__(self, id, information):
-        self.id = id
-        self._information = information
-
-    @property
-    def title(self):
-        return self._information.title
-
-    @property
-    def description(self):
-        return self._information.description
-
-    @apply
-    def members():
-        def get(self):
-            return self._information.principals
-        def set(self, value):
-            self._information.principals = value
-        return property(get, set)
-
-    def __repr__(self):
-        return 'GroupInfo(%r)' % self.id
-
-
-class GroupFolder(BTreeContainer):
-
-    interface.implements(
-        interfaces.IAuthenticatorPlugin,
-        interfaces.IQuerySchemaSearch,
-        IGroupFolder)
-
-    schema = IGroupSearchCriteria
-
-    def __init__(self, prefix=u''):
-        super(GroupFolder, self).__init__()
-        self.prefix = prefix
-        # __inversemapping is used to map principals to groups
-        self.__inverseMapping = BTrees.OOBTree.OOBTree()
-
-    def __setitem__(self, name, value):
-        BTreeContainer.__setitem__(self, name, value)
-        group_id = self._groupid(value)
-        self._addPrincipalsToGroup(value.principals, group_id)
-        if value.principals:
-            event.notify(
-                interfaces.PrincipalsAddedToGroup(
-                    value.principals, self.__parent__.prefix + group_id))
-        group = principalfolder.Principal(self.prefix + name)
-        event.notify(interfaces.GroupAdded(group))
-
-    def __delitem__(self, name):
-        value = self[name]
-        group_id = self._groupid(value)
-        self._removePrincipalsFromGroup(value.principals, group_id)
-        if value.principals:
-            event.notify(
-                interfaces.PrincipalsRemovedFromGroup(
-                    value.principals, self.__parent__.prefix + group_id))
-        BTreeContainer.__delitem__(self, name)
-
-    def _groupid(self, group):
-        return self.prefix+group.__name__
-
-    def _addPrincipalsToGroup(self, principal_ids, group_id):
-        for principal_id in principal_ids:
-            self.__inverseMapping[principal_id] = (
-                self.__inverseMapping.get(principal_id, ())
-                + (group_id,))
-
-    def _removePrincipalsFromGroup(self, principal_ids, group_id):
-        for principal_id in principal_ids:
-            groups = self.__inverseMapping.get(principal_id)
-            if groups is None:
-                return
-            new = tuple([id for id in groups if id != group_id])
-            if new:
-                self.__inverseMapping[principal_id] = new
-            else:
-                del self.__inverseMapping[principal_id]
-
-    def getGroupsForPrincipal(self, principalid):
-        """Get groups the given principal belongs to"""
-        return self.__inverseMapping.get(principalid, ())
-
-    def getPrincipalsForGroup(self, groupid):
-        """Get principals which belong to the group"""
-        return self[groupid].principals
-
-    def search(self, query, start=None, batch_size=None):
-        """ Search for groups"""
-        search = query.get('search')
-        if search is not None:
-            n = 0
-            search = search.lower()
-            for i, (id, groupinfo) in enumerate(self.items()):
-                if (search in groupinfo.title.lower() or
-                    (groupinfo.description and 
-                     search in groupinfo.description.lower())):
-                    if not ((start is not None and i < start)
-                            or
-                            (batch_size is not None and n >= batch_size)):
-                        n += 1
-                        yield self.prefix + id
-
-    def authenticateCredentials(self, credentials):
-        # user folders don't authenticate
-        pass
-
-    def principalInfo(self, id):
-        if id.startswith(self.prefix):
-            id = id[len(self.prefix):]
-            info = self.get(id)
-            if info is not None:
-                return GroupInfo(
-                    self.prefix+id, info)
-
-class GroupCycle(Exception):
-    """There is a cyclic relationship among groups
-    """
-
-class InvalidPrincipalIds(Exception):
-    """A user has a group id for a group that can't be found
-    """
-
-class InvalidGroupId(Exception):
-    """A user has a group id for a group that can't be found
-    """
-
-def nocycles(principal_ids, seen, getPrincipal):
-    for principal_id in principal_ids:
-        if principal_id in seen:
-            raise GroupCycle(principal_id, seen)
-        seen.append(principal_id)
-        principal = getPrincipal(principal_id)
-        nocycles(principal.groups, seen, getPrincipal)
-        seen.pop()
-
-class GroupInformation(persistent.Persistent):
-
-    interface.implements(IGroupInformation, IGroupContained)
-
-    __parent__ = __name__ = None
-
-    _principals = ()
-
-    def __init__(self, title='', description=''):
-        self.title = title
-        self.description = description
-
-    def setPrincipals(self, prinlist, check=True):
-        # method is not a part of the interface
-        parent = self.__parent__
-        old = self._principals
-        self._principals = tuple(prinlist)
-
-        if parent is not None:
-            oldset = set(old)
-            new = set(prinlist)
-            group_id = parent._groupid(self)
-            removed = oldset - new
-            added = new - oldset
-            try:
-                parent._removePrincipalsFromGroup(removed, group_id)
-            except AttributeError:
-                removed = None
-
-            try:
-                parent._addPrincipalsToGroup(added, group_id)
-            except AttributeError:
-                added = None
-
-            if check:
-                try:
-                    principalsUtility = component.getUtility(IAuthentication)
-                    nocycles(new, [], principalsUtility.getPrincipal)
-                except GroupCycle:
-                    # abort
-                    self.setPrincipals(old, False)
-                    raise
-            # now that we've gotten past the checks, fire the events.
-            if removed:
-                event.notify(
-                    interfaces.PrincipalsRemovedFromGroup(
-                        removed, self.__parent__.__parent__.prefix + group_id))
-            if added:
-                event.notify(
-                    interfaces.PrincipalsAddedToGroup(
-                        added, self.__parent__.__parent__.prefix + group_id))
-
-    principals = property(lambda self: self._principals, setPrincipals)
-
-
-def specialGroups(event):
-    principal = event.principal
-    if (IGroup.providedBy(principal) or
-        not IGroupAwarePrincipal.providedBy(principal)):
-        return
-
-    everyone = component.queryUtility(IEveryoneGroup)
-    if everyone is not None:
-        principal.groups.append(everyone.id)
-
-    auth = component.queryUtility(IAuthenticatedGroup)
-    if auth is not None:
-        principal.groups.append(auth.id)
-
-
-def setGroupsForPrincipal(event):
-    """Set group information when a principal is created"""
-
-    principal = event.principal
-    if not IGroupAwarePrincipal.providedBy(principal):
-        return
-
-    authentication = event.authentication
-
-    for name, plugin in authentication.getAuthenticatorPlugins():
-        if not IGroupFolder.providedBy(plugin):
-            continue
-        groupfolder = plugin
-        principal.groups.extend(
-            [authentication.prefix + id
-             for id in groupfolder.getGroupsForPrincipal(principal.id)
-             ])
-        id = principal.id
-        prefix = authentication.prefix + groupfolder.prefix
-        if id.startswith(prefix) and id[len(prefix):] in groupfolder:
-            alsoProvides(principal, IGroup)
-
- at component.adapter(interfaces.IFoundPrincipalCreated)
-def setMemberSubscriber(event):
-    """adds `getMembers`, `setMembers` to groups made from IGroupPrincipalInfo.
-    """
-    info = event.info
-    if IGroupPrincipalInfo.providedBy(info):
-        principal = event.principal
-        principal.getMembers = lambda : info.members
-        def setMembers(value):
-            info.members = value
-        principal.setMembers = setMembers
-        alsoProvides(principal, IMemberAwareGroup)

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/groupfolder.txt
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/groupfolder.txt	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/groupfolder.txt	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,425 +0,0 @@
-=============
-Group Folders
-=============
-
-Group folders provide support for groups information stored in the ZODB.  They
-are persistent, and must be contained within the PAUs that use them.
-
-Like other principals, groups are created when they are needed.
-
-Group folders contain group-information objects that contain group information.
-We create group information using the `GroupInformation` class:
-
-  >>> import zope.app.authentication.groupfolder
-  >>> g1 = zope.app.authentication.groupfolder.GroupInformation("Group 1")
-
-  >>> groups = zope.app.authentication.groupfolder.GroupFolder('group.')
-  >>> groups['g1'] = g1
-
-Note that when group-info is added, a GroupAdded event is generated:
-
-  >>> from zope.app.authentication import interfaces
-  >>> from zope.component.eventtesting import getEvents
-  >>> getEvents(interfaces.IGroupAdded)
-  [<GroupAdded 'group.g1'>]
-
-Groups are defined with respect to an authentication service.  Groups
-must be accessible via an authentication service and can contain
-principals accessible via an authentication service.
-
-To illustrate the group interaction with the authentication service,
-we'll create a sample authentication service:
-
-  >>> from zope import interface
-  >>> from zope.authentication.interfaces import IAuthentication
-  >>> from zope.authentication.interfaces import PrincipalLookupError
-  >>> from zope.security.interfaces import IGroupAwarePrincipal
-  >>> from zope.app.authentication.groupfolder import setGroupsForPrincipal
-
-  >>> class Principal:
-  ...     interface.implements(IGroupAwarePrincipal)
-  ...     def __init__(self, id, title='', description=''):
-  ...         self.id, self.title, self.description = id, title, description
-  ...         self.groups = []
-
-  >>> class PrincipalCreatedEvent:
-  ...     def __init__(self, authentication, principal):
-  ...         self.authentication = authentication
-  ...         self.principal = principal
-
-  >>> from zope.app.authentication import principalfolder
-
-  >>> class Principals:
-  ...
-  ...     interface.implements(IAuthentication)
-  ...
-  ...     def __init__(self, groups, prefix='auth.'):
-  ...         self.prefix = prefix
-  ...         self.principals = {
-  ...            'p1': principalfolder.PrincipalInfo('p1', '', '', ''),
-  ...            'p2': principalfolder.PrincipalInfo('p2', '', '', ''),
-  ...            'p3': principalfolder.PrincipalInfo('p3', '', '', ''),
-  ...            'p4': principalfolder.PrincipalInfo('p4', '', '', ''),
-  ...            }
-  ...         self.groups = groups
-  ...         groups.__parent__ = self
-  ...
-  ...     def getAuthenticatorPlugins(self):
-  ...         return [('principals', self.principals), ('groups', self.groups)]
-  ...
-  ...     def getPrincipal(self, id):
-  ...         if not id.startswith(self.prefix):
-  ...             raise PrincipalLookupError(id)
-  ...         id = id[len(self.prefix):]
-  ...         info = self.principals.get(id)
-  ...         if info is None:
-  ...             info = self.groups.principalInfo(id)
-  ...             if info is None:
-  ...                raise PrincipalLookupError(id)
-  ...         principal = Principal(self.prefix+info.id, 
-  ...                               info.title, info.description)
-  ...         setGroupsForPrincipal(PrincipalCreatedEvent(self, principal))
-  ...         return principal
-
-This class doesn't really implement the full `IAuthentication` interface, but
-it implements the `getPrincipal` method used by groups. It works very much
-like the pluggable authentication utility.  It creates principals on demand. It
-calls `setGroupsForPrincipal`, which is normally called as an event subscriber,
-when principals are created. In order for `setGroupsForPrincipal` to find out
-group folder, we have to register it as a utility:
-
-  >>> from zope.app.authentication.interfaces import IAuthenticatorPlugin
-  >>> from zope.component import provideUtility
-  >>> provideUtility(groups, IAuthenticatorPlugin)
-
-We will create and register a new principals utility:
-
-  >>> principals = Principals(groups)
-  >>> provideUtility(principals, IAuthentication)
-
-Now we can set the principals on the group:
-
-  >>> g1.principals = ['auth.p1', 'auth.p2']
-  >>> g1.principals
-  ('auth.p1', 'auth.p2')
-
-Adding principals fires an event.
-
-  >>> getEvents(interfaces.IPrincipalsAddedToGroup)[-1]
-  <PrincipalsAddedToGroup ['auth.p1', 'auth.p2'] u'auth.group.g1'>
-
-We can now look up groups for the principals:
-
-  >>> groups.getGroupsForPrincipal('auth.p1')
-  (u'group.g1',)
-
-Note that the group id is a concatenation of the group-folder prefix
-and the name of the group-information object within the folder.
-
-If we delete a group:
-
-  >>> del groups['g1']
-
-then the groups folder loses the group information for that group's
-principals:
-
-  >>> groups.getGroupsForPrincipal('auth.p1')
-  ()
-
-but the principal information on the group is unchanged:
-
-  >>> g1.principals
-  ('auth.p1', 'auth.p2')
-
-It also fires an event showing that the principals are removed from the group
-(g1 is group information, not a zope.security.interfaces.IGroup).
-
-  >>> getEvents(interfaces.IPrincipalsRemovedFromGroup)[-1]
-  <PrincipalsRemovedFromGroup ['auth.p1', 'auth.p2'] u'auth.group.g1'>
-
-Adding the group sets the folder principal information.  Let's use a
-different group name:
-
-  >>> groups['G1'] = g1
-
-  >>> groups.getGroupsForPrincipal('auth.p1')
-  (u'group.G1',)
-
-Here we see that the new name is reflected in the group information.
-
-An event is fired, as usual.
-
-  >>> getEvents(interfaces.IPrincipalsAddedToGroup)[-1]
-  <PrincipalsAddedToGroup ['auth.p1', 'auth.p2'] u'auth.group.G1'>
-
-In terms of member events (principals added and removed from groups), we have
-now seen that events are fired when a group information object is added and
-when it is removed from a group folder; and we have seen that events are fired
-when a principal is added to an already-registered group.  Events are also
-fired when a principal is removed from an already-registered group.  Let's
-quickly see some more examples.
-
-  >>> g1.principals = ('auth.p1', 'auth.p3', 'auth.p4')
-  >>> getEvents(interfaces.IPrincipalsAddedToGroup)[-1]
-  <PrincipalsAddedToGroup ['auth.p3', 'auth.p4'] u'auth.group.G1'>
-  >>> getEvents(interfaces.IPrincipalsRemovedFromGroup)[-1]
-  <PrincipalsRemovedFromGroup ['auth.p2'] u'auth.group.G1'>
-  >>> g1.principals = ('auth.p1', 'auth.p2')
-  >>> getEvents(interfaces.IPrincipalsAddedToGroup)[-1]
-  <PrincipalsAddedToGroup ['auth.p2'] u'auth.group.G1'>
-  >>> getEvents(interfaces.IPrincipalsRemovedFromGroup)[-1]
-  <PrincipalsRemovedFromGroup ['auth.p3', 'auth.p4'] u'auth.group.G1'>
-
-Groups can contain groups:
-
-  >>> g2 = zope.app.authentication.groupfolder.GroupInformation("Group Two")
-  >>> groups['G2'] = g2
-  >>> g2.principals = ['auth.group.G1']
-
-  >>> groups.getGroupsForPrincipal('auth.group.G1')
-  (u'group.G2',)
-
-  >>> old = getEvents(interfaces.IPrincipalsAddedToGroup)[-1]
-  >>> old
-  <PrincipalsAddedToGroup ['auth.group.G1'] u'auth.group.G2'>
-
-Groups cannot contain cycles:
-
-  >>> g1.principals = ('auth.p1', 'auth.p2', 'auth.group.G2')
-  ... # doctest: +NORMALIZE_WHITESPACE
-  Traceback (most recent call last):
-  ...
-  GroupCycle: (u'auth.group.G1', 
-               ['auth.p2', u'auth.group.G1', u'auth.group.G2'])
-
-Trying to do so does not fire an event.
-
-  >>> getEvents(interfaces.IPrincipalsAddedToGroup)[-1] is old
-  True
-
-They need not be hierarchical:
-
-  >>> ga = zope.app.authentication.groupfolder.GroupInformation("Group A")
-  >>> groups['GA'] = ga
-
-  >>> gb = zope.app.authentication.groupfolder.GroupInformation("Group B")
-  >>> groups['GB'] = gb
-  >>> gb.principals = ['auth.group.GA']
-
-  >>> gc = zope.app.authentication.groupfolder.GroupInformation("Group C")
-  >>> groups['GC'] = gc
-  >>> gc.principals = ['auth.group.GA']
-
-  >>> gd = zope.app.authentication.groupfolder.GroupInformation("Group D")
-  >>> groups['GD'] = gd
-  >>> gd.principals = ['auth.group.GA', 'auth.group.GB']
-
-  >>> ga.principals = ['auth.p1']
-
-Group folders provide a very simple search interface.  They perform
-simple string searches on group titles and descriptions.
-
-  >>> list(groups.search({'search': 'grou'})) # doctest: +NORMALIZE_WHITESPACE
-  [u'group.G1', u'group.G2',
-   u'group.GA', u'group.GB', u'group.GC', u'group.GD']
-
-  >>> list(groups.search({'search': 'two'}))
-  [u'group.G2']
-
-They also support batching:
-
-  >>> list(groups.search({'search': 'grou'}, 2, 3))
-  [u'group.GA', u'group.GB', u'group.GC']
-
-
-If you don't supply a search key, no results will be returned:
-
-  >>> list(groups.search({}))
-  []
-
-Identifying groups
-------------------
-The function, `setGroupsForPrincipal`, is a subscriber to
-principal-creation events.  It adds any group-folder-defined groups to
-users in those groups:
-
-  >>> principal = principals.getPrincipal('auth.p1')
-
-  >>> principal.groups
-  [u'auth.group.G1', u'auth.group.GA']
-
-Of course, this applies to groups too:
-
-  >>> principal = principals.getPrincipal('auth.group.G1')
-  >>> principal.id
-  'auth.group.G1'
-
-  >>> principal.groups
-  [u'auth.group.G2']
-
-In addition to setting principal groups, the `setGroupsForPrincipal`
-function also declares the `IGroup` interface on groups:
-
-  >>> [iface.__name__ for iface in interface.providedBy(principal)]
-  ['IGroup', 'IGroupAwarePrincipal']
-
-  >>> [iface.__name__
-  ...  for iface in interface.providedBy(principals.getPrincipal('auth.p1'))]
-  ['IGroupAwarePrincipal']
-
-Special groups
---------------
-Two special groups, Authenticated, and Everyone may apply to users
-created by the pluggable-authentication utility.  There is a
-subscriber, specialGroups, that will set these groups on any non-group
-principals if IAuthenticatedGroup, or IEveryoneGroup utilities are
-provided.
-
-Lets define a group-aware principal:
-
-  >>> import zope.security.interfaces
-  >>> class GroupAwarePrincipal(Principal):
-  ...     interface.implements(zope.security.interfaces.IGroupAwarePrincipal)
-  ...     def __init__(self, id):
-  ...         Principal.__init__(self, id)
-  ...         self.groups = []
-
-If we notify the subscriber with this principal, nothing will happen
-because the groups haven't been defined:
-
-  >>> prin = GroupAwarePrincipal('x')
-  >>> event = interfaces.FoundPrincipalCreated(42, prin, {})
-  >>> zope.app.authentication.groupfolder.specialGroups(event)
-  >>> prin.groups
-  []
-
-Now, if we define the Everybody group:
-
-  >>> import zope.authentication.interfaces
-  >>> class EverybodyGroup(Principal):
-  ...     interface.implements(zope.authentication.interfaces.IEveryoneGroup)
-
-  >>> everybody = EverybodyGroup('all')
-  >>> provideUtility(everybody, zope.authentication.interfaces.IEveryoneGroup)
-
-Then the group will be added to the principal:
-
-  >>> zope.app.authentication.groupfolder.specialGroups(event)
-  >>> prin.groups
-  ['all']
-
-Similarly for the authenticated group:
-
-  >>> class AuthenticatedGroup(Principal):
-  ...     interface.implements(
-  ...         zope.authentication.interfaces.IAuthenticatedGroup)
-
-  >>> authenticated = AuthenticatedGroup('auth')
-  >>> provideUtility(authenticated, zope.authentication.interfaces.IAuthenticatedGroup)
-
-Then the group will be added to the principal:
-
-  >>> prin.groups = []
-  >>> zope.app.authentication.groupfolder.specialGroups(event)
-  >>> prin.groups.sort()
-  >>> prin.groups
-  ['all', 'auth']
-
-These groups are only added to non-group principals:
-
-  >>> prin.groups = []
-  >>> interface.directlyProvides(prin, zope.security.interfaces.IGroup)
-  >>> zope.app.authentication.groupfolder.specialGroups(event)
-  >>> prin.groups
-  []
-
-And they are only added to group aware principals:
-
-  >>> class SolitaryPrincipal:
-  ...     interface.implements(zope.security.interfaces.IPrincipal)
-  ...     id = title = description = ''
-
-  >>> event = interfaces.FoundPrincipalCreated(42, SolitaryPrincipal(), {})
-  >>> zope.app.authentication.groupfolder.specialGroups(event)
-  >>> prin.groups
-  []
-
-Member-aware groups
--------------------
-The groupfolder includes a subscriber that gives group principals the
-zope.security.interfaces.IGroupAware interface and an implementation thereof.
-This allows groups to be able to get and set their members.
-
-Given an info object and a group...
-
-    >>> class DemoGroupInformation(object):
-    ...     interface.implements(
-    ...         zope.app.authentication.groupfolder.IGroupInformation)
-    ...     def __init__(self, title, description, principals):
-    ...         self.title = title
-    ...         self.description = description
-    ...         self.principals = principals
-    ...
-    >>> i = DemoGroupInformation(
-    ...     'Managers', 'Taskmasters', ('joe', 'jane'))
-    ...
-    >>> info = zope.app.authentication.groupfolder.GroupInfo(
-    ...     'groups.managers', i)
-    >>> class DummyGroup(object):
-    ...     interface.implements(IGroupAwarePrincipal)
-    ...     def __init__(self, id, title=u'', description=u''):
-    ...         self.id = id
-    ...         self.title = title
-    ...         self.description = description
-    ...         self.groups = []
-    ...
-    >>> principal = DummyGroup('foo')
-    >>> zope.security.interfaces.IMemberAwareGroup.providedBy(principal)
-    False
-
-...when you call the subscriber, it adds the two pseudo-methods to the
-principal and makes the principal provide the IMemberAwareGroup interface.
-
-    >>> zope.app.authentication.groupfolder.setMemberSubscriber(
-    ...     interfaces.FoundPrincipalCreated(
-    ...         'dummy auth (ignored)', principal, info))
-    >>> principal.getMembers()
-    ('joe', 'jane')
-    >>> principal.setMembers(('joe', 'jane', 'jaimie'))
-    >>> principal.getMembers()
-    ('joe', 'jane', 'jaimie')
-    >>> zope.security.interfaces.IMemberAwareGroup.providedBy(principal)
-    True
-
-The two methods work with the value on the IGroupInformation object.
-
-    >>> i.principals == principal.getMembers()
-    True
-
-Limitation
-==========
-
-The current group-folder design has an important limitation!
-
-There is no point in assigning principals to a group 
-from a group folder unless the principal is from the same pluggable
-authentication utility.
-
-o If a principal is from a higher authentication utility, the user
-  will not get the group definition. Why? Because the principals
-  group assignments are set when the principal is authenticated. At
-  that point, the current site is the site containing the principal
-  definition. Groups defined in lower sites will not be consulted,
-
-o It is impossible to assign users from lower authentication
-  utilities because they can't be seen when managing the group,
-  from the site containing the group.
-
-A better design might be to store user-role assignments independent of
-the group definitions and to look for assignments during (url)
-traversal.  This could get quite complex though.
-
-While it is possible to have multiple authentication utilities long a
-URL path, it is generally better to stick to a simpler model in which
-there is only one authentication utility along a URL path (in addition
-to the global utility, which is used for bootstrapping purposes).

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/groupfolder.zcml
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/groupfolder.zcml	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/groupfolder.zcml	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,66 +0,0 @@
-<configure
-    xmlns="http://namespaces.zope.org/zope"
-    i18n_domain="zope"
-    >
-
-  <class class=".groupfolder.GroupInformation">
-    <implements
-        interface="zope.annotation.interfaces.IAttributeAnnotatable"
-        />
-    <require
-        permission="zope.ManageServices"
-        interface=".groupfolder.IGroupInformation
-                   .groupfolder.IGroupContained"
-        set_schema=".groupfolder.IGroupInformation"
-        />
-  </class>
-
-  <class class=".groupfolder.GroupFolder">
-    <implements
-        interface=".groupfolder.IGroupFolder"
-        />
-    <require
-        permission="zope.ManageServices"
-        interface="zope.container.interfaces.IContainer
-                   zope.container.interfaces.INameChooser"
-        />
-  </class>
-
-  <adapter
-      provides="zope.container.interfaces.INameChooser"
-      for=".groupfolder.IGroupFolder"
-      factory=".idpicker.IdPicker"
-      />
-
-  <subscriber
-      for=".interfaces.IPrincipalCreated"
-      handler=".groupfolder.specialGroups"
-      />
-
-  <subscriber
-      for=".interfaces.IPrincipalCreated"
-      handler=".groupfolder.setGroupsForPrincipal"
-      />
-
-  <subscriber
-      handler=".groupfolder.setMemberSubscriber"
-      />
-
-  <include package=".browser" file="groupfolder.zcml" />
-
-  <!-- Registering documentation with API doc -->
-  <configure
-      xmlns:apidoc="http://namespaces.zope.org/apidoc"
-      xmlns:zcml="http://namespaces.zope.org/zcml"
-      zcml:condition="have apidoc">
-
-    <apidoc:bookchapter
-        id="groupfolder"
-        title="Group Folders"
-        doc_path="groupfolder.txt"
-        parent="security/authentication"
-        />
-
-  </configure>
-
-</configure>

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/httpplugins.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/httpplugins.py	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/httpplugins.py	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,142 +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.
-#
-##############################################################################
-"""PAS plugins related to HTTP
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-import base64
-from persistent import Persistent
-from zope.interface import implements, Interface
-from zope.publisher.interfaces.http import IHTTPRequest
-from zope.schema import TextLine
-
-from zope.container.contained import Contained
-from zope.app.authentication import interfaces
-
-
-class IHTTPBasicAuthRealm(Interface):
-    """HTTP Basic Auth Realm
-
-    Represents the realm string that is used during basic HTTP authentication
-    """
-
-    realm = TextLine(title=u'Realm',
-                     description=u'HTTP Basic Authentication Realm',
-                     required=True,
-                     default=u'Zope')
-
-
-class HTTPBasicAuthCredentialsPlugin(Persistent, Contained):
-
-    implements(interfaces.ICredentialsPlugin, IHTTPBasicAuthRealm)
-
-    realm = 'Zope'
-
-    protocol = 'http auth'
-
-    def extractCredentials(self, request):
-        """Extracts HTTP basic auth credentials from a request.
-
-        First we need to create a request that contains some credentials.
-
-          >>> from zope.publisher.browser import TestRequest
-          >>> request = TestRequest(
-          ...     environ={'HTTP_AUTHORIZATION': u'Basic bWdyOm1ncnB3'})
-
-        Now create the plugin and get the credentials.
-
-          >>> plugin = HTTPBasicAuthCredentialsPlugin()
-          >>> plugin.extractCredentials(request)
-          {'login': u'mgr', 'password': u'mgrpw'}
-
-        Make sure we return `None`, if no authentication header has been
-        specified.
-
-          >>> print plugin.extractCredentials(TestRequest())
-          None
-
-        Also, this plugin can *only* handle basic authentication.
-
-          >>> request = TestRequest(environ={'HTTP_AUTHORIZATION': 'foo bar'})
-          >>> print plugin.extractCredentials(TestRequest())
-          None
-
-        This plugin only works with HTTP requests.
-
-          >>> from zope.publisher.base import TestRequest
-          >>> print plugin.extractCredentials(TestRequest('/'))
-          None
-
-        """
-        if not IHTTPRequest.providedBy(request):
-            return None
-
-        if request._auth:
-            if request._auth.lower().startswith(u'basic '):
-                credentials = request._auth.split()[-1]
-                login, password = base64.decodestring(credentials).split(':')
-                return {'login': login.decode('utf-8'),
-                        'password': password.decode('utf-8')}
-        return None
-
-    def challenge(self, request):
-        """Issues an HTTP basic auth challenge for credentials.
-
-        The challenge is issued by setting the appropriate response headers.
-        To illustrate, we'll create a plugin:
-
-          >>> plugin = HTTPBasicAuthCredentialsPlugin()
-
-        The plugin adds its challenge to the HTTP response.
-
-          >>> from zope.publisher.browser import TestRequest
-          >>> request = TestRequest()
-          >>> response = request.response
-          >>> plugin.challenge(request)
-          True
-          >>> response._status
-          401
-          >>> response.getHeader('WWW-Authenticate', literal=True)
-          'basic realm="Zope"'
-
-        Notice that the realm is quoted, as per RFC 2617.
-
-        The plugin only works with HTTP requests.
-
-          >>> from zope.publisher.base import TestRequest
-          >>> request = TestRequest('/')
-          >>> response = request.response
-          >>> print plugin.challenge(request)
-          False
-
-        """
-        if not IHTTPRequest.providedBy(request):
-            return False
-        request.response.setHeader("WWW-Authenticate",
-                                   'basic realm="%s"' % self.realm,
-                                   literal=True)
-        request.response.setStatus(401)
-        return True
-
-    def logout(self, request):
-        """Always returns False as logout is not supported by basic auth.
-
-          >>> plugin = HTTPBasicAuthCredentialsPlugin()
-          >>> from zope.publisher.browser import TestRequest
-          >>> plugin.logout(TestRequest())
-          False
-
-        """
-        return False

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/httpplugins.zcml
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/httpplugins.zcml	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/httpplugins.zcml	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,25 +0,0 @@
-<configure
-    xmlns="http://namespaces.zope.org/zope"
-    i18n_domain="zope"
-    >
-
-  <utility
-      name="Zope Realm Basic-Auth"
-      provides=".interfaces.ICredentialsPlugin"
-      factory=".httpplugins.HTTPBasicAuthCredentialsPlugin"
-      />
-
-  <class class=".httpplugins.HTTPBasicAuthCredentialsPlugin">
-    <implements
-        interface="zope.annotation.interfaces.IAttributeAnnotatable"
-        />
-    <require
-        permission="zope.ManageServices"
-        interface=".httpplugins.IHTTPBasicAuthRealm"
-        set_schema=".httpplugins.IHTTPBasicAuthRealm"
-        />
-  </class>
-
-  <include package=".browser" file="httpplugins.zcml" />
-
-</configure>

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/password.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/password.py	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/password.py	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,28 +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.
-#
-##############################################################################
-"""Backward compatibility imports for password managers
-
-$Id$
-"""
-__docformat__ = 'restructuredtext'
-
-# BBB: the password managers were moved into zope.password package.
-from zope.password.password import (
-    PlainTextPasswordManager,
-    MD5PasswordManager,
-    SHA1PasswordManager,
-    SSHAPasswordManager,
-    managers,
-    )
-from zope.password.vocabulary import PasswordManagerNamesVocabulary

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/password.zcml
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/password.zcml	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/password.zcml	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,5 +0,0 @@
-<configure xmlns="http://namespaces.zope.org/zope">
-
-  <include package="zope.password" />
-
-</configure>

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/placelesssetup.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/placelesssetup.py	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/placelesssetup.py	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,26 +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.
-#
-##############################################################################
-"""Pluggable Authentication Service Placeless Setup
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-
-# BBB: the password managers were moved to zope.password package
-from zope.password.testing import setUpPasswordManagers
-
-class PlacelessSetup(object):
-
-    def setUp(self):
-        setUpPasswordManagers()

Copied: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/ftpplugins.py (from rev 108407, zope.pluggableauth/trunk/src/zope/pluggableauth/ftpplugins.py)
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/ftpplugins.py	                        (rev 0)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/ftpplugins.py	2010-01-23 17:52:16 UTC (rev 108409)
@@ -0,0 +1,65 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""PAS plugins related to FTP
+"""
+__docformat__ = 'restructuredtext'
+
+from zope.interface import implements
+from zope.publisher.interfaces.ftp import IFTPRequest
+
+from zope.app.authentication import interfaces
+
+class FTPCredentialsPlugin(object):
+
+    implements(interfaces.ICredentialsPlugin)
+
+    def extractCredentials(self, request):
+        """Extracts the FTP credentials from a request.
+
+        First we need to create a FTP request that contains some credentials.
+        Note the path is a required in the envirnoment.
+
+          >>> from zope.publisher.ftp import FTPRequest
+          >>> from StringIO import StringIO
+          >>> request = FTPRequest(StringIO(''),
+          ...                      {'credentials': ('bob', '123'),
+          ...                       'path': '/a/b/c'})
+
+        Now we create the plugin and get the credentials.
+
+          >>> plugin = FTPCredentialsPlugin()
+          >>> plugin.extractCredentials(request)
+          {'login': u'bob', 'password': u'123'}
+
+        This only works for FTPRequests.
+
+          >>> from zope.publisher.base import TestRequest
+          >>> print plugin.extractCredentials(TestRequest('/'))
+          None
+
+        """
+        if not IFTPRequest.providedBy(request):
+            return None
+
+        if request._auth:
+            login, password = request._auth
+            return {'login': login.decode('utf-8'),
+                    'password': password.decode('utf-8')}
+        return None
+
+    def challenge(self, request):
+        return False
+
+    def logout(self, request):
+        return False

Copied: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/ftpplugins.zcml (from rev 108407, zope.pluggableauth/trunk/src/zope/pluggableauth/ftpplugins.zcml)
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/ftpplugins.zcml	                        (rev 0)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/ftpplugins.zcml	2010-01-23 17:52:16 UTC (rev 108409)
@@ -0,0 +1,12 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    i18n_domain="zope"
+    >
+
+  <utility
+      name="FTP Credentials"
+      provides=".interfaces.ICredentialsPlugin"
+      factory=".ftpplugins.FTPCredentialsPlugin"
+      />
+
+</configure>

Copied: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/generic.py (from rev 108407, zope.pluggableauth/trunk/src/zope/pluggableauth/generic.py)
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/generic.py	                        (rev 0)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/generic.py	2010-01-23 17:52:16 UTC (rev 108409)
@@ -0,0 +1,94 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Generic PAS Plugins
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+from zope.interface import implements
+from zope.authentication.interfaces import IUnauthenticatedPrincipal
+
+from zope.app.authentication import interfaces
+
+
+class NoChallengeCredentialsPlugin(object):
+    """A plugin that doesn't challenge if the principal is authenticated.
+
+    There are two reasonable ways to handle an unauthorized error for an
+    authenticated principal:
+
+      - Inform the user of the unauthorized error
+
+      - Let the user login with a different set of credentials
+
+    Since either approach is reasonable, we need to give the site manager
+    some way of specifying one of the two policies.
+
+    By default, a user will be challenged for a new set of credentials if
+    unauthorized. A site manager can insert this plugin in the front of the
+    plugin list to prevent that challenge from occurring. This will
+    typically result in an 'Unauthorized' message to the user.
+
+    The 'challenge' behavior of the plugin is simple. To illustrate, we'll
+    create a plugin:
+
+      >>> challenger = NoChallengeCredentialsPlugin()
+
+    and a test request with an authenticated principal:
+
+      >>> from zope.publisher.browser import TestRequest
+      >>> request = TestRequest()
+      >>> IUnauthenticatedPrincipal.providedBy(request.principal)
+      False
+
+    When we challenge using the plugin:
+
+      >>> challenger.challenge(request)
+      True
+
+    we get a value that signals the PAU that this plugin successfully
+    challenged the user (even though it actually did nothing). The PAU
+    will stop trying to challenge and the user will not get a chance to
+    provide different credentials. The result is typically an error message.
+
+    On the other hand, if the user is unauthenticated:
+
+      >>> class Principal(object):
+      ...     implements(IUnauthenticatedPrincipal)
+      >>> request.setPrincipal(Principal())
+      >>> IUnauthenticatedPrincipal.providedBy(request.principal)
+      True
+
+    the plugin challenge will return None:
+
+      >>> print challenger.challenge(request)
+      None
+
+    signaling the PAU that it should try the next plugin for a challenge. If
+    the PAU is configured properly, the user will receive a challenge and be
+    allowed to provide different credentials.
+    """
+    implements(interfaces.ICredentialsPlugin)
+
+    def extractCredentials(self, request):
+        return None
+
+    def challenge(self, request):
+        if not IUnauthenticatedPrincipal.providedBy(request.principal):
+            return True
+        return None
+
+    def logout(self, request):
+        return False
+

Copied: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/httpplugins.py (from rev 108407, zope.pluggableauth/trunk/src/zope/pluggableauth/httpplugins.py)
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/httpplugins.py	                        (rev 0)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/httpplugins.py	2010-01-23 17:52:16 UTC (rev 108409)
@@ -0,0 +1,142 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""PAS plugins related to HTTP
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import base64
+from persistent import Persistent
+from zope.interface import implements, Interface
+from zope.publisher.interfaces.http import IHTTPRequest
+from zope.schema import TextLine
+
+from zope.container.contained import Contained
+from zope.app.authentication import interfaces
+
+
+class IHTTPBasicAuthRealm(Interface):
+    """HTTP Basic Auth Realm
+
+    Represents the realm string that is used during basic HTTP authentication
+    """
+
+    realm = TextLine(title=u'Realm',
+                     description=u'HTTP Basic Authentication Realm',
+                     required=True,
+                     default=u'Zope')
+
+
+class HTTPBasicAuthCredentialsPlugin(Persistent, Contained):
+
+    implements(interfaces.ICredentialsPlugin, IHTTPBasicAuthRealm)
+
+    realm = 'Zope'
+
+    protocol = 'http auth'
+
+    def extractCredentials(self, request):
+        """Extracts HTTP basic auth credentials from a request.
+
+        First we need to create a request that contains some credentials.
+
+          >>> from zope.publisher.browser import TestRequest
+          >>> request = TestRequest(
+          ...     environ={'HTTP_AUTHORIZATION': u'Basic bWdyOm1ncnB3'})
+
+        Now create the plugin and get the credentials.
+
+          >>> plugin = HTTPBasicAuthCredentialsPlugin()
+          >>> plugin.extractCredentials(request)
+          {'login': u'mgr', 'password': u'mgrpw'}
+
+        Make sure we return `None`, if no authentication header has been
+        specified.
+
+          >>> print plugin.extractCredentials(TestRequest())
+          None
+
+        Also, this plugin can *only* handle basic authentication.
+
+          >>> request = TestRequest(environ={'HTTP_AUTHORIZATION': 'foo bar'})
+          >>> print plugin.extractCredentials(TestRequest())
+          None
+
+        This plugin only works with HTTP requests.
+
+          >>> from zope.publisher.base import TestRequest
+          >>> print plugin.extractCredentials(TestRequest('/'))
+          None
+
+        """
+        if not IHTTPRequest.providedBy(request):
+            return None
+
+        if request._auth:
+            if request._auth.lower().startswith(u'basic '):
+                credentials = request._auth.split()[-1]
+                login, password = base64.decodestring(credentials).split(':')
+                return {'login': login.decode('utf-8'),
+                        'password': password.decode('utf-8')}
+        return None
+
+    def challenge(self, request):
+        """Issues an HTTP basic auth challenge for credentials.
+
+        The challenge is issued by setting the appropriate response headers.
+        To illustrate, we'll create a plugin:
+
+          >>> plugin = HTTPBasicAuthCredentialsPlugin()
+
+        The plugin adds its challenge to the HTTP response.
+
+          >>> from zope.publisher.browser import TestRequest
+          >>> request = TestRequest()
+          >>> response = request.response
+          >>> plugin.challenge(request)
+          True
+          >>> response._status
+          401
+          >>> response.getHeader('WWW-Authenticate', literal=True)
+          'basic realm="Zope"'
+
+        Notice that the realm is quoted, as per RFC 2617.
+
+        The plugin only works with HTTP requests.
+
+          >>> from zope.publisher.base import TestRequest
+          >>> request = TestRequest('/')
+          >>> response = request.response
+          >>> print plugin.challenge(request)
+          False
+
+        """
+        if not IHTTPRequest.providedBy(request):
+            return False
+        request.response.setHeader("WWW-Authenticate",
+                                   'basic realm="%s"' % self.realm,
+                                   literal=True)
+        request.response.setStatus(401)
+        return True
+
+    def logout(self, request):
+        """Always returns False as logout is not supported by basic auth.
+
+          >>> plugin = HTTPBasicAuthCredentialsPlugin()
+          >>> from zope.publisher.browser import TestRequest
+          >>> plugin.logout(TestRequest())
+          False
+
+        """
+        return False

Copied: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/httpplugins.zcml (from rev 108407, zope.pluggableauth/trunk/src/zope/pluggableauth/httpplugins.zcml)
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/httpplugins.zcml	                        (rev 0)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/httpplugins.zcml	2010-01-23 17:52:16 UTC (rev 108409)
@@ -0,0 +1,25 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    i18n_domain="zope"
+    >
+
+  <utility
+      name="Zope Realm Basic-Auth"
+      provides=".interfaces.ICredentialsPlugin"
+      factory=".httpplugins.HTTPBasicAuthCredentialsPlugin"
+      />
+
+  <class class=".httpplugins.HTTPBasicAuthCredentialsPlugin">
+    <implements
+        interface="zope.annotation.interfaces.IAttributeAnnotatable"
+        />
+    <require
+        permission="zope.ManageServices"
+        interface=".httpplugins.IHTTPBasicAuthRealm"
+        set_schema=".httpplugins.IHTTPBasicAuthRealm"
+        />
+  </class>
+
+  <include package=".browser" file="httpplugins.zcml" />
+
+</configure>

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/principalfolder.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/principalfolder.py	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/principalfolder.py	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,566 +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.
-#
-##############################################################################
-"""ZODB-based Authentication Source
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-
-from persistent import Persistent
-from zope import interface
-from zope import component
-from zope.event import notify
-from zope.schema import Text, TextLine, Password, Choice
-from zope.publisher.interfaces import IRequest
-
-from zope.authentication.interfaces import IAuthentication
-from zope.container.interfaces import DuplicateIDError
-from zope.container.contained import Contained
-from zope.container.constraints import contains, containers
-from zope.container.btree import BTreeContainer
-from zope.password.interfaces import IPasswordManager
-from zope.app.authentication.i18n import ZopeMessageFactory as _
-
-from zope.app.authentication import interfaces
-
-
-class IInternalPrincipal(interface.Interface):
-    """Principal information"""
-
-    login = TextLine(
-        title=_("Login"),
-        description=_("The Login/Username of the principal. "
-                      "This value can change."))
-
-    def setPassword(password, passwordManagerName=None):
-        pass
-
-    password = Password(
-        title=_("Password"),
-        description=_("The password for the principal."))
-
-    passwordManagerName = Choice(
-        title=_("Password Manager"),
-        vocabulary="Password Manager Names",
-        description=_("The password manager will be used"
-            " for encode/check the password"),
-        default="SSHA",
-        # TODO: The password manager name may be changed only
-        # if the password changed
-        readonly=True
-        )
-
-    title = TextLine(
-        title=_("Title"),
-        description=_("Provides a title for the principal."))
-
-    description = Text(
-        title=_("Description"),
-        description=_("Provides a description for the principal."),
-        required=False,
-        missing_value='',
-        default=u'')
-
-
-class IInternalPrincipalContainer(interface.Interface):
-    """A container that contains internal principals."""
-
-    prefix = TextLine(
-        title=_("Prefix"),
-        description=_(
-        "Prefix to be added to all principal ids to assure "
-        "that all ids are unique within the authentication service"),
-        missing_value=u"",
-        default=u'',
-        readonly=True)
-
-    def getIdByLogin(login):
-        """Return the principal id currently associated with login.
-
-        The return value includes the container prefix, but does not
-        include the PAU prefix.
-
-        KeyError is raised if no principal is associated with login.
-
-        """
-
-    contains(IInternalPrincipal)
-
-
-class IInternalPrincipalContained(interface.Interface):
-    """Principal information"""
-
-    containers(IInternalPrincipalContainer)
-
-
-class ISearchSchema(interface.Interface):
-    """Search Interface for this Principal Provider"""
-
-    search = TextLine(
-        title=_("Search String"),
-        description=_("A Search String"),
-        required=False,
-        default=u'',
-        missing_value=u'')
-
-
-class InternalPrincipal(Persistent, Contained):
-    """An internal principal for Persistent Principal Folder."""
-
-    interface.implements(IInternalPrincipal, IInternalPrincipalContained)
-
-    # If you're searching for self._passwordManagerName, or self._password
-    # probably you just need to evolve the database to new generation
-    # at /++etc++process/@@generations.html
-
-    # NOTE: All changes needs to be synchronized with the evolver at
-    # zope.app.zopeappgenerations.evolve2
-
-    def __init__(self, login, password, title, description=u'',
-            passwordManagerName="SSHA"):
-        self._login = login
-        self._passwordManagerName = passwordManagerName
-        self.password = password
-        self.title = title
-        self.description = description
-
-    def getPasswordManagerName(self):
-        return self._passwordManagerName
-
-    passwordManagerName = property(getPasswordManagerName)
-
-    def _getPasswordManager(self):
-        return component.getUtility(
-            IPasswordManager, self.passwordManagerName)
-
-    def getPassword(self):
-        return self._password
-
-    def setPassword(self, password, passwordManagerName=None):
-        if passwordManagerName is not None:
-            self._passwordManagerName = passwordManagerName
-        passwordManager = self._getPasswordManager()
-        self._password = passwordManager.encodePassword(password)
-
-    password = property(getPassword, setPassword)
-
-    def checkPassword(self, password):
-        passwordManager = self._getPasswordManager()
-        return passwordManager.checkPassword(self.password, password)
-
-    def getPassword(self):
-        return self._password
-
-    def getLogin(self):
-        return self._login
-
-    def setLogin(self, login):
-        oldLogin = self._login
-        self._login = login
-        if self.__parent__ is not None:
-            try:
-                self.__parent__.notifyLoginChanged(oldLogin, self)
-            except ValueError:
-                self._login = oldLogin
-                raise
-
-    login = property(getLogin, setLogin)
-
-
-class PrincipalInfo(object):
-    """An implementation of IPrincipalInfo used by the principal folder.
-
-    A principal info is created with id, login, title, and description:
-
-      >>> info = PrincipalInfo('users.foo', 'foo', 'Foo', 'An over-used term.')
-      >>> info
-      PrincipalInfo('users.foo')
-      >>> info.id
-      'users.foo'
-      >>> info.login
-      'foo'
-      >>> info.title
-      'Foo'
-      >>> info.description
-      'An over-used term.'
-
-    """
-    interface.implements(interfaces.IPrincipalInfo)
-
-    def __init__(self, id, login, title, description):
-        self.id = id
-        self.login = login
-        self.title = title
-        self.description = description
-
-    def __repr__(self):
-        return 'PrincipalInfo(%r)' % self.id
-
-
-class PrincipalFolder(BTreeContainer):
-    """A Persistent Principal Folder and Authentication plugin.
-
-    See principalfolder.txt for details.
-    """
-
-    interface.implements(interfaces.IAuthenticatorPlugin,
-                         interfaces.IQuerySchemaSearch,
-                         IInternalPrincipalContainer)
-
-    schema = ISearchSchema
-
-    def __init__(self, prefix=''):
-        self.prefix = unicode(prefix)
-        super(PrincipalFolder, self).__init__()
-        self.__id_by_login = self._newContainerData()
-
-    def notifyLoginChanged(self, oldLogin, principal):
-        """Notify the Container about changed login of a principal.
-
-        We need this, so that our second tree can be kept up-to-date.
-        """
-        # A user with the new login already exists
-        if principal.login in self.__id_by_login:
-            raise ValueError('Principal Login already taken!')
-
-        del self.__id_by_login[oldLogin]
-        self.__id_by_login[principal.login] = principal.__name__
-
-    def __setitem__(self, id, principal):
-        """Add principal information.
-
-        Create a Principal Folder
-
-            >>> pf = PrincipalFolder()
-
-        Create a principal with 1 as id
-        Add a login attr since __setitem__ is in need of one
-
-            >>> principal = Principal(1)
-            >>> principal.login = 1
-
-        Add the principal within the Principal Folder
-
-            >>> pf.__setitem__(u'1', principal)
-
-        Try to add another principal with the same id.
-        It should raise a DuplicateIDError
-
-            >>> try:
-            ...     pf.__setitem__(u'1', principal)
-            ... except DuplicateIDError, e:
-            ...     pass
-            >>>
-        """
-        # A user with the new login already exists
-        if principal.login in self.__id_by_login:
-            raise DuplicateIDError('Principal Login already taken!')
-
-        super(PrincipalFolder, self).__setitem__(id, principal)
-        self.__id_by_login[principal.login] = id
-
-    def __delitem__(self, id):
-        """Remove principal information."""
-        principal = self[id]
-        super(PrincipalFolder, self).__delitem__(id)
-        del self.__id_by_login[principal.login]
-
-    def authenticateCredentials(self, credentials):
-        """Return principal info if credentials can be authenticated
-        """
-        if not isinstance(credentials, dict):
-            return None
-        if not ('login' in credentials and 'password' in credentials):
-            return None
-        id = self.__id_by_login.get(credentials['login'])
-        if id is None:
-            return None
-        internal = self[id]
-        if not internal.checkPassword(credentials["password"]):
-            return None
-        return PrincipalInfo(self.prefix + id, internal.login, internal.title,
-                             internal.description)
-
-    def principalInfo(self, id):
-        if id.startswith(self.prefix):
-            internal = self.get(id[len(self.prefix):])
-            if internal is not None:
-                return PrincipalInfo(id, internal.login, internal.title,
-                                     internal.description)
-
-    def getIdByLogin(self, login):
-        return self.prefix + self.__id_by_login[login]
-
-    def search(self, query, start=None, batch_size=None):
-        """Search through this principal provider."""
-        search = query.get('search')
-        if search is None:
-            return
-        search = search.lower()
-        n = 1
-        for i, value in enumerate(self.values()):
-            if (search in value.title.lower() or
-                search in value.description.lower() or
-                search in value.login.lower()):
-                if not ((start is not None and i < start)
-                        or (batch_size is not None and n > batch_size)):
-                    n += 1
-                    yield self.prefix + value.__name__
-
-class Principal(object):
-    """A group-aware implementation of zope.security.interfaces.IPrincipal.
-
-    A principal is created with an ID:
-
-      >>> p = Principal(1)
-      >>> p
-      Principal(1)
-      >>> p.id
-      1
-
-    title and description may also be provided:
-
-      >>> p = Principal('george', 'George', 'A site member.')
-      >>> p
-      Principal('george')
-      >>> p.id
-      'george'
-      >>> p.title
-      'George'
-      >>> p.description
-      'A site member.'
-
-    The `groups` is a simple list, filled in by plugins.
-
-      >>> p.groups
-      []
-
-    The `allGroups` attribute is a readonly iterable of the full closure of the
-    groups in the `groups` attribute--that is, if the principal is a direct
-    member of the 'Administrators' group, and the 'Administrators' group is
-    a member of the 'Reviewers' group, then p.groups would be 
-    ['Administrators'] and list(p.allGroups) would be
-    ['Administrators', 'Reviewers'].
-
-    To illustrate this, we'll need to set up a dummy authentication utility,
-    and a few principals.  Our main principal will also gain some groups, as if
-    plugins had added the groups to the list.  This is all setup--skip to the
-    next block to actually see `allGroups` in action.
-    
-      >>> p.groups.extend(
-      ...     ['content_administrators', 'zope_3_project',
-      ...      'list_administrators', 'zpug'])
-      >>> editor = Principal('editors', 'Content Editors')
-      >>> creator = Principal('creators', 'Content Creators')
-      >>> reviewer = Principal('reviewers', 'Content Reviewers')
-      >>> reviewer.groups.extend(['editors', 'creators'])
-      >>> usermanager = Principal('user_managers', 'User Managers')
-      >>> contentAdmin = Principal(
-      ...     'content_administrators', 'Content Administrators')
-      >>> contentAdmin.groups.extend(['reviewers', 'user_managers'])
-      >>> zope3Dev = Principal('zope_3_project', 'Zope 3 Developer')
-      >>> zope3ListAdmin = Principal(
-      ...     'zope_3_list_admin', 'Zope 3 List Administrators')
-      >>> zope3ListAdmin.groups.append('zope_3_project') # duplicate, but
-      ... # should only appear in allGroups once
-      >>> listAdmin = Principal('list_administrators', 'List Administrators')
-      >>> listAdmin.groups.append('zope_3_list_admin')
-      >>> zpugMember = Principal('zpug', 'ZPUG Member')
-      >>> martians = Principal('martians', 'Martians') # not in p's allGroups
-      >>> group_data = dict((p.id, p) for p in (
-      ...     editor, creator, reviewer, usermanager, contentAdmin,
-      ...     zope3Dev, zope3ListAdmin, listAdmin, zpugMember, martians))
-      >>> class DemoAuth(object):
-      ...     interface.implements(IAuthentication)
-      ...     def getPrincipal(self, id):
-      ...         return group_data[id]
-      ...
-      >>> demoAuth = DemoAuth()
-      >>> component.provideUtility(demoAuth)
-
-    Now, we have a user with the following groups (lowest level are p's direct
-    groups, and lines show membership):
-
-      editors  creators
-         \------/
-             |                                     zope_3_project (duplicate)
-          reviewers  user_managers                          |
-               \---------/                           zope_3_list_admin
-                    |                                       |
-          content_administrators   zope_3_project   list_administrators   zpug
-
-    The allGroups value includes all of the shown groups, and with
-    'zope_3_project' only appearing once.
-
-      >>> p.groups # doctest: +NORMALIZE_WHITESPACE
-      ['content_administrators', 'zope_3_project', 'list_administrators',
-       'zpug']
-      >>> list(p.allGroups) # doctest: +NORMALIZE_WHITESPACE
-      ['content_administrators', 'reviewers', 'editors', 'creators',
-       'user_managers', 'zope_3_project', 'list_administrators',
-       'zope_3_list_admin', 'zpug']
-    """
-    interface.implements(interfaces.IPrincipal)
-
-    def __init__(self, id, title=u'', description=u''):
-        self.id = id
-        self.title = title
-        self.description = description
-        self.groups = []
-
-    def __repr__(self):
-        return 'Principal(%r)' % self.id
-
-    @property
-    def allGroups(self):
-        if self.groups:
-            seen = set()
-            principals = component.getUtility(IAuthentication)
-            stack = [iter(self.groups)]
-            while stack:
-                try:
-                    group_id = stack[-1].next()
-                except StopIteration:
-                    stack.pop()
-                else:
-                    if group_id not in seen:
-                        yield group_id
-                        seen.add(group_id)
-                        group = principals.getPrincipal(group_id)
-                        stack.append(iter(group.groups))
-
-class AuthenticatedPrincipalFactory(object):
-    """Creates 'authenticated' principals.
-
-    An authenticated principal is created as a result of an authentication
-    operation.
-
-    To use the factory, create it with the info (interfaces.IPrincipalInfo) of
-    the principal to create and a request:
-
-      >>> info = PrincipalInfo('users.mary', 'mary', 'Mary', 'The site admin.')
-      >>> from zope.publisher.base import TestRequest
-      >>> request = TestRequest('/')
-      >>> factory = AuthenticatedPrincipalFactory(info, request)
-
-    The factory must be called with a pluggable-authentication object:
-
-      >>> class Auth:
-      ...     prefix = 'auth.'
-      >>> auth = Auth()
-
-      >>> principal = factory(auth)
-
-    The factory uses the pluggable authentication and the info to
-    create a principal with the same ID, title, and description:
-
-      >>> principal.id
-      'auth.users.mary'
-      >>> principal.title
-      'Mary'
-      >>> principal.description
-      'The site admin.'
-
-    It also fires an AuthenticatedPrincipalCreatedEvent:
-
-      >>> from zope.component.eventtesting import getEvents
-      >>> [event] = getEvents(interfaces.IAuthenticatedPrincipalCreated)
-      >>> event.principal is principal, event.authentication is auth
-      (True, True)
-      >>> event.info
-      PrincipalInfo('users.mary')
-      >>> event.request is request
-      True
-
-    Listeners can subscribe to this event to perform additional operations
-    when the authenticated principal is created.
-
-    For information on how factories are used in the authentication process,
-    see README.txt.
-    """
-    component.adapts(interfaces.IPrincipalInfo, IRequest)
-
-    interface.implements(interfaces.IAuthenticatedPrincipalFactory)
-
-    def __init__(self, info, request):
-        self.info = info
-        self.request = request
-
-    def __call__(self, authentication):
-        principal = Principal(authentication.prefix + self.info.id,
-                              self.info.title,
-                              self.info.description)
-        notify(interfaces.AuthenticatedPrincipalCreated(
-            authentication, principal, self.info, self.request))
-        return principal
-
-
-class FoundPrincipalFactory(object):
-    """Creates 'found' principals.
-
-    A 'found' principal is created as a result of a principal lookup.
-
-    To use the factory, create it with the info (interfaces.IPrincipalInfo) of
-    the principal to create:
-
-      >>> info = PrincipalInfo('users.sam', 'sam', 'Sam', 'A site user.')
-      >>> factory = FoundPrincipalFactory(info)
-
-    The factory must be called with a pluggable-authentication object:
-
-      >>> class Auth:
-      ...     prefix = 'auth.'
-      >>> auth = Auth()
-
-      >>> principal = factory(auth)
-
-    The factory uses the pluggable-authentication object and the info
-    to create a principal with the same ID, title, and description:
-
-      >>> principal.id
-      'auth.users.sam'
-      >>> principal.title
-      'Sam'
-      >>> principal.description
-      'A site user.'
-
-    It also fires a FoundPrincipalCreatedEvent:
-
-      >>> from zope.component.eventtesting import getEvents
-      >>> [event] = getEvents(interfaces.IFoundPrincipalCreated)
-      >>> event.principal is principal, event.authentication is auth
-      (True, True)
-      >>> event.info
-      PrincipalInfo('users.sam')
-
-    Listeners can subscribe to this event to perform additional operations
-    when the 'found' principal is created.
-
-    For information on how factories are used in the authentication process,
-    see README.txt.
-    """
-    component.adapts(interfaces.IPrincipalInfo)
-
-    interface.implements(interfaces.IFoundPrincipalFactory)
-
-    def __init__(self, info):
-        self.info = info
-
-    def __call__(self, authentication):
-        principal = Principal(authentication.prefix + self.info.id,
-                              self.info.title,
-                              self.info.description)
-        notify(interfaces.FoundPrincipalCreated(authentication,
-                                                principal, self.info))
-        return principal

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/principalfolder.txt
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/principalfolder.txt	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/principalfolder.txt	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,170 +0,0 @@
-================
-Principal Folder
-================
-
-Principal folders contain principal-information objects that contain principal
-information. We create an internal principal using the `InternalPrincipal`
-class:
-
-  >>> from zope.app.authentication.principalfolder import InternalPrincipal
-  >>> p1 = InternalPrincipal('login1', '123', "Principal 1",
-  ...     passwordManagerName="SHA1")
-  >>> p2 = InternalPrincipal('login2', '456', "The Other One")
-
-and add them to a principal folder:
-
-  >>> from zope.app.authentication.principalfolder import PrincipalFolder
-  >>> principals = PrincipalFolder('principal.')
-  >>> principals['p1'] = p1
-  >>> principals['p2'] = p2
-
-Authentication
---------------
-
-Principal folders provide the `IAuthenticatorPlugin` interface. When we
-provide suitable credentials:
-
-  >>> from zope.testing.doctestunit import pprint
-  >>> principals.authenticateCredentials({'login': 'login1', 'password': '123'})
-  PrincipalInfo(u'principal.p1')
-
-We get back a principal id and supplementary information, including the
-principal title and description.  Note that the principal id is a concatenation
-of the principal-folder prefix and the name of the principal-information object
-within the folder.
-
-None is returned if the credentials are invalid:
-
-  >>> principals.authenticateCredentials({'login': 'login1',
-  ...                                     'password': '1234'})
-  >>> principals.authenticateCredentials(42)
-
-Search
-------
-
-Principal folders also provide the IQuerySchemaSearch interface.  This
-supports both finding principal information based on their ids:
-
-  >>> principals.principalInfo('principal.p1')
-  PrincipalInfo('principal.p1')
-
-  >>> principals.principalInfo('p1')
-
-and searching for principals based on a search string:
-
-  >>> list(principals.search({'search': 'other'}))
-  [u'principal.p2']
-
-  >>> list(principals.search({'search': 'OTHER'}))
-  [u'principal.p2']
-
-  >>> list(principals.search({'search': ''}))
-  [u'principal.p1', u'principal.p2']
-
-  >>> list(principals.search({'search': 'eek'}))
-  []
-
-  >>> list(principals.search({}))
-  []
-
-If there are a large number of matches:
-
-  >>> for i in range(20):
-  ...     i = str(i)
-  ...     p = InternalPrincipal('l'+i, i, "Dude "+i)
-  ...     principals[i] = p
-
-  >>> pprint(list(principals.search({'search': 'D'})))
-  [u'principal.0',
-   u'principal.1',
-   u'principal.10',
-   u'principal.11',
-   u'principal.12',
-   u'principal.13',
-   u'principal.14',
-   u'principal.15',
-   u'principal.16',
-   u'principal.17',
-   u'principal.18',
-   u'principal.19',
-   u'principal.2',
-   u'principal.3',
-   u'principal.4',
-   u'principal.5',
-   u'principal.6',
-   u'principal.7',
-   u'principal.8',
-   u'principal.9']
-
-We can use batching parameters to specify a subset of results:
-
-  >>> pprint(list(principals.search({'search': 'D'}, start=17)))
-  [u'principal.7',
-   u'principal.8',
-   u'principal.9']
-
-  >>> pprint(list(principals.search({'search': 'D'}, batch_size=5)))
-  [u'principal.0',
-   u'principal.1',
-   u'principal.10',
-   u'principal.11',
-   u'principal.12']
-
-  >>> pprint(list(principals.search({'search': 'D'}, start=5, batch_size=5)))
-  [u'principal.13',
-   u'principal.14',
-   u'principal.15',
-   u'principal.16',
-   u'principal.17']
-
-There is an additional method that allows requesting the principal id
-associated with a login id.  The method raises KeyError when there is
-no associated principal::
-
-  >>> principals.getIdByLogin("not-there")
-  Traceback (most recent call last):
-  KeyError: 'not-there'
-
-If there is a matching principal, the id is returned::
-
-  >>> principals.getIdByLogin("login1")
-  u'principal.p1'
-
-Changing credentials
---------------------
-
-Credentials can be changed by modifying principal-information objects:
-
-  >>> p1.login = 'bob'
-  >>> p1.password = 'eek'
-
-  >>> principals.authenticateCredentials({'login': 'bob', 'password': 'eek'})
-  PrincipalInfo(u'principal.p1')
-
-  >>> principals.authenticateCredentials({'login': 'login1',
-  ...                                     'password': 'eek'})
-
-  >>> principals.authenticateCredentials({'login': 'bob',
-  ...                                     'password': '123'})
-
-
-It is an error to try to pick a login name that is already taken:
-
-  >>> p1.login = 'login2'
-  Traceback (most recent call last):
-  ...
-  ValueError: Principal Login already taken!
-
-If such an attempt is made, the data are unchanged:
-
-  >>> principals.authenticateCredentials({'login': 'bob', 'password': 'eek'})
-  PrincipalInfo(u'principal.p1')
-
-Removing principals
--------------------
-
-Of course, if a principal is removed, we can no-longer authenticate it:
-
-  >>> del principals['p1']
-  >>> principals.authenticateCredentials({'login': 'bob',
-  ...                                     'password': 'eek'})

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/principalfolder.zcml
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/principalfolder.zcml	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/principalfolder.zcml	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,59 +0,0 @@
-<configure
-    xmlns="http://namespaces.zope.org/zope"
-    i18n_domain="zope"
-    >
-
-  <class class=".principalfolder.InternalPrincipal">
-    <require
-        permission="zope.ManageServices"
-        interface=".principalfolder.IInternalPrincipal"
-        set_schema=".principalfolder.IInternalPrincipal"
-        />
-  </class>
-
-  <class class=".principalfolder.PrincipalFolder">
-
-    <implements
-        interface="zope.annotation.interfaces.IAttributeAnnotatable"
-        />
-
-    <require
-        permission="zope.ManageServices"
-        interface="zope.container.interfaces.IContainer"
-        />
-
-    <require
-        permission="zope.ManageServices"
-        attributes="prefix"
-        />
-
-  </class>
-
-  <adapter
-      provides="zope.container.interfaces.INameChooser"
-      for=".principalfolder.IInternalPrincipalContainer"
-      factory=".idpicker.IdPicker"
-      />
-
-  <adapter factory=".principalfolder.FoundPrincipalFactory" />
-
-  <adapter factory=".principalfolder.AuthenticatedPrincipalFactory" />
-
-  <include package=".browser" file="principalfolder.zcml" />
-
-  <!-- Registering documentation with API doc -->
-  <configure
-      xmlns:apidoc="http://namespaces.zope.org/apidoc"
-      xmlns:zcml="http://namespaces.zope.org/zcml"
-      zcml:condition="have apidoc">
-
-    <apidoc:bookchapter
-        id="principalfolder"
-        title="Principal Folder"
-        doc_path="principalfolder.txt"
-        parent="security/authentication"
-        />
-
-  </configure>
-
-</configure>

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/vocabulary.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/vocabulary.py	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/vocabulary.py	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,96 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Plugin Vocabulary.
-
-This vocabulary provides terms for authentication utility plugins.
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-
-import zope.dublincore.interfaces
-from zope import interface, component, i18n
-from zope.schema import vocabulary
-from zope.schema.interfaces import IVocabularyFactory
-
-from zope.app.authentication.i18n import ZopeMessageFactory as _
-
-from zope.app.authentication import interfaces
-
-UTILITY_TITLE = _(
-    'zope.app.authentication.vocabulary-utility-plugin-title',
-    '${name} (a utility)')
-CONTAINED_TITLE = _(
-    'zope.app.authentication.vocabulary-contained-plugin-title',
-    '${name} (in contents)')
-MISSING_TITLE = _(
-    'zope.app.authentication.vocabulary-missing-plugin-title',
-    '${name} (not found; deselecting will remove)')
-
-def _pluginVocabulary(context, interface, attr_name):
-    """Vocabulary that provides names of plugins of a specified interface.
-
-    Given an interface, the options should include the unique names of all of
-    the plugins that provide the specified interface for the current context--
-    which is expected to be a pluggable authentication utility, hereafter
-    referred to as a PAU).
-
-    These plugins may be objects contained within the PAU ("contained
-    plugins"), or may be utilities registered for the specified
-    interface, found in the context of the PAU ("utility plugins").
-    Contained plugins mask utility plugins of the same name.
-
-    The vocabulary also includes the current values of the PAU even if they do
-    not correspond to a contained or utility plugin.
-    """
-    terms = {}
-    isPAU = interfaces.IPluggableAuthentication.providedBy(context)
-    if isPAU:
-        for k, v in context.items():
-            if interface.providedBy(v):
-                dc = zope.dublincore.interfaces.IDCDescriptiveProperties(
-                    v, None)
-                if dc is not None and dc.title:
-                    title = dc.title
-                else:
-                    title = k
-                terms[k] = vocabulary.SimpleTerm(
-                    k, k.encode('base64').strip(), i18n.Message(
-                        CONTAINED_TITLE, mapping={'name': title}))
-    utils = component.getUtilitiesFor(interface, context)
-    for nm, util in utils:
-        if nm not in terms:
-            terms[nm] = vocabulary.SimpleTerm(
-                nm, nm.encode('base64').strip(), i18n.Message(
-                    UTILITY_TITLE, mapping={'name': nm}))
-    if isPAU:
-        for nm in set(getattr(context, attr_name)):
-            if nm not in terms:
-                terms[nm] = vocabulary.SimpleTerm(
-                    nm, nm.encode('base64').strip(), i18n.Message(
-                        MISSING_TITLE, mapping={'name': nm}))
-    return vocabulary.SimpleVocabulary(
-        [term for nm, term in sorted(terms.items())])
-
-def authenticatorPlugins(context):
-    return _pluginVocabulary(
-        context, interfaces.IAuthenticatorPlugin, 'authenticatorPlugins')
-
-interface.alsoProvides(authenticatorPlugins, IVocabularyFactory)
-
-def credentialsPlugins(context):
-    return _pluginVocabulary(
-        context, interfaces.ICredentialsPlugin, 'credentialsPlugins')
-
-interface.alsoProvides(credentialsPlugins, IVocabularyFactory)

Deleted: zope.pluggableauth/trunk/src/zope/pluggableauth/vocabulary.txt
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/vocabulary.txt	2010-01-23 17:40:50 UTC (rev 108408)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/vocabulary.txt	2010-01-23 17:52:16 UTC (rev 108409)
@@ -1,203 +0,0 @@
-============
-Vocabularies
-============
-
-The vocabulary module provides vocabularies for the authenticator plugins and
-the credentials plugins.
-
-The options should include the unique names of all of the plugins that provide
-the appropriate interface (interfaces.ICredentialsPlugin or
-interfaces.IAuthentiatorPlugin, respectively) for the current context-- which
-is expected to be a pluggable authentication utility, hereafter referred to as
-a PAU.
-
-These names may be for objects contained within the PAU ("contained
-plugins"), or may be utilities registered for the specified interface,
-found in the context of the PAU ("utility plugins").  Contained
-plugins mask utility plugins of the same name.  They also may be names
-currently selected in the PAU that do not actually have a
-corresponding plugin at this time.
-
-Here is a short example of how the vocabulary should work.  Let's say we're
-working with authentication plugins.  We'll create some faux
-authentication plugins, and register some of them as utilities and put
-others in a faux PAU.
-
-    >>> from zope.app.authentication import interfaces
-    >>> from zope import interface, component
-    >>> class DemoPlugin(object):
-    ...     interface.implements(interfaces.IAuthenticatorPlugin)
-    ...     def __init__(self, name):
-    ...         self.name = name
-    ...
-    >>> utility_plugins = dict(
-    ...     (i, DemoPlugin(u'Plugin %d' % i)) for i in range(4))
-    >>> contained_plugins = dict(
-    ...     (i, DemoPlugin(u'Plugin %d' % i)) for i in range(1, 5))
-    >>> sorted(utility_plugins.keys())
-    [0, 1, 2, 3]
-    >>> for p in utility_plugins.values():
-    ...     component.provideUtility(p, name=p.name)
-    ...
-    >>> sorted(contained_plugins.keys()) # 1 will mask utility plugin 1
-    [1, 2, 3, 4]
-    >>> class DemoAuth(dict):
-    ...     interface.implements(interfaces.IPluggableAuthentication)
-    ...     def __init__(self, *args, **kwargs):
-    ...         super(DemoAuth, self).__init__(*args, **kwargs)
-    ...         self.authenticatorPlugins = (u'Plugin 3', u'Plugin X')
-    ...         self.credentialsPlugins = (u'Plugin 4', u'Plugin X')
-    ...
-    >>> auth = DemoAuth((p.name, p) for p in contained_plugins.values())
-
-    >>> @component.adapter(interface.Interface)
-    ... @interface.implementer(component.IComponentLookup)
-    ... def getSiteManager(context):
-    ...     return component.getGlobalSiteManager()
-    ...
-    >>> component.provideAdapter(getSiteManager)
-
-We are now ready to create a vocabulary that we can use.  The context is
-our faux authentication utility, `auth`.
-
-    >>> from zope.app.authentication import vocabulary
-    >>> vocab = vocabulary.authenticatorPlugins(auth)
-
-Iterating over the vocabulary results in all of the terms, in a relatively
-arbitrary order of their names.  (This vocabulary should typically use a
-widget that sorts values on the basis of localized collation order of the
-term titles.)
-
-    >>> [term.value for term in vocab] # doctest: +NORMALIZE_WHITESPACE
-    [u'Plugin 0', u'Plugin 1', u'Plugin 2', u'Plugin 3', u'Plugin 4',
-     u'Plugin X']
-
-Similarly, we can use `in` to test for the presence of values in the
-vocabulary.
-
-    >>> ['Plugin %s' % i in vocab for i in range(-1, 6)]
-    [False, True, True, True, True, True, False]
-    >>> 'Plugin X' in vocab
-    True
-
-The length reports the expected value.
-
-    >>> len(vocab)
-    6
-
-One can get a term for a given value using `getTerm()`; its token, in
-turn, should also return the same effective term from `getTermByToken`.
-
-    >>> values = ['Plugin 0', 'Plugin 1', 'Plugin 2', 'Plugin 3', 'Plugin 4',
-    ...           'Plugin X']
-    >>> for val in values:
-    ...     term = vocab.getTerm(val)
-    ...     assert term.value == val
-    ...     term2 = vocab.getTermByToken(term.token)
-    ...     assert term2.token == term.token
-    ...     assert term2.value == val
-    ...
-
-The terms have titles, which are message ids that show the plugin title or id
-and whether the plugin is a utility or just contained in the auth utility.
-We'll give one of the plugins a dublin core title just to show the
-functionality.
-
-    >>> import zope.dublincore.interfaces
-    >>> class ISpecial(interface.Interface):
-    ...     pass
-    ...
-    >>> interface.directlyProvides(contained_plugins[1], ISpecial)
-    >>> class DemoDCAdapter(object):
-    ...     interface.implements(
-    ...         zope.dublincore.interfaces.IDCDescriptiveProperties)
-    ...     component.adapts(ISpecial)
-    ...     def __init__(self, context):
-    ...         pass
-    ...     title = u'Special Title'
-    ...
-    >>> component.provideAdapter(DemoDCAdapter)
-
-We need to regenerate the vocabulary, since it calculates all of its data at
-once.
-
-    >>> vocab = vocabulary.authenticatorPlugins(auth)
-
-Now we'll check the titles.  We'll have to translate them to see what we
-expect.
-
-    >>> from zope import i18n
-    >>> import pprint
-    >>> pprint.pprint([i18n.translate(term.title) for term in vocab])
-    [u'Plugin 0 (a utility)',
-     u'Special Title (in contents)',
-     u'Plugin 2 (in contents)',
-     u'Plugin 3 (in contents)',
-     u'Plugin 4 (in contents)',
-     u'Plugin X (not found; deselecting will remove)']
-
-credentialsPlugins
-------------------
-
-For completeness, we'll do the same review of the credentialsPlugins.
-
-    >>> class DemoPlugin(object):
-    ...     interface.implements(interfaces.ICredentialsPlugin)
-    ...     def __init__(self, name):
-    ...         self.name = name
-    ...
-    >>> utility_plugins = dict(
-    ...     (i, DemoPlugin(u'Plugin %d' % i)) for i in range(4))
-    >>> contained_plugins = dict(
-    ...     (i, DemoPlugin(u'Plugin %d' % i)) for i in range(1, 5))
-    >>> for p in utility_plugins.values():
-    ...     component.provideUtility(p, name=p.name)
-    ...
-    >>> auth = DemoAuth((p.name, p) for p in contained_plugins.values())
-    >>> vocab = vocabulary.credentialsPlugins(auth)
-
-Iterating over the vocabulary results in all of the terms, in a relatively
-arbitrary order of their names.  (This vocabulary should typically use a
-widget that sorts values on the basis of localized collation order of the term
-titles.) Similarly, we can use `in` to test for the presence of values in the
-vocabulary. The length reports the expected value.
-
-    >>> [term.value for term in vocab] # doctest: +NORMALIZE_WHITESPACE
-    [u'Plugin 0', u'Plugin 1', u'Plugin 2', u'Plugin 3', u'Plugin 4',
-     u'Plugin X']
-    >>> ['Plugin %s' % i in vocab for i in range(-1, 6)]
-    [False, True, True, True, True, True, False]
-    >>> 'Plugin X' in vocab
-    True
-    >>> len(vocab)
-    6
-
-One can get a term for a given value using `getTerm()`; its token, in
-turn, should also return the same effective term from `getTermByToken`.
-
-    >>> values = ['Plugin 0', 'Plugin 1', 'Plugin 2', 'Plugin 3', 'Plugin 4',
-    ...           'Plugin X']
-    >>> for val in values:
-    ...     term = vocab.getTerm(val)
-    ...     assert term.value == val
-    ...     term2 = vocab.getTermByToken(term.token)
-    ...     assert term2.token == term.token
-    ...     assert term2.value == val
-    ...
-
-The terms have titles, which are message ids that show the plugin title or id
-and whether the plugin is a utility or just contained in the auth utility.
-We'll give one of the plugins a dublin core title just to show the
-functionality. We need to regenerate the vocabulary, since it calculates all
-of its data at once. Then we'll check the titles.  We'll have to translate
-them to see what we expect.
-
-    >>> interface.directlyProvides(contained_plugins[1], ISpecial)
-    >>> vocab = vocabulary.credentialsPlugins(auth)
-    >>> pprint.pprint([i18n.translate(term.title) for term in vocab])
-    [u'Plugin 0 (a utility)',
-     u'Special Title (in contents)',
-     u'Plugin 2 (in contents)',
-     u'Plugin 3 (in contents)',
-     u'Plugin 4 (in contents)',
-     u'Plugin X (not found; deselecting will remove)']



More information about the checkins mailing list