[Checkins] SVN: zope.pluggableauth/trunk/ Initial Py 3.3 port and tox testing.

Stephen Richter cvs-admin at zope.org
Thu Feb 21 21:39:29 UTC 2013


Log message for revision 129592:
  Initial Py 3.3 port and tox testing.
  

Changed:
  _U  zope.pluggableauth/trunk/
  U   zope.pluggableauth/trunk/CHANGES.txt
  A   zope.pluggableauth/trunk/MANIFEST.in
  U   zope.pluggableauth/trunk/bootstrap.py
  U   zope.pluggableauth/trunk/buildout.cfg
  U   zope.pluggableauth/trunk/setup.py
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/README.txt
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/factories.py
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/ftpplugins.py
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/generic.py
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/groupfolder.py
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/groupfolder.txt
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/httpplugins.py
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/idpicker.py
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/principalfolder.py
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/principalfolder.txt
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/session.py
  U   zope.pluggableauth/trunk/src/zope/pluggableauth/tests.py
  A   zope.pluggableauth/trunk/tox.ini

-=-

Property changes on: zope.pluggableauth/trunk
___________________________________________________________________
Modified: svn:ignore
   - bin
build
dist
lib
develop-eggs
eggs
parts
.installed.cfg

   + .tox
bin
build
dist
lib
develop-eggs
eggs
parts
.installed.cfg


Modified: zope.pluggableauth/trunk/CHANGES.txt
===================================================================
--- zope.pluggableauth/trunk/CHANGES.txt	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/CHANGES.txt	2013-02-21 21:39:29 UTC (rev 129592)
@@ -2,9 +2,13 @@
 Changes
 =======
 
-2.0 (unreleased)
-----------------
+2.0.0a1 (unreleased)
+--------------------
 
+- Added `tox.ini` and `MANIFEST.in`.
+
+- Added support for Python 3.3.
+
 - Replaced deprecated ``zope.component.adapts`` usage with equivalent
   ``zope.component.adapter`` decorator.
 

Added: zope.pluggableauth/trunk/MANIFEST.in
===================================================================
--- zope.pluggableauth/trunk/MANIFEST.in	                        (rev 0)
+++ zope.pluggableauth/trunk/MANIFEST.in	2013-02-21 21:39:29 UTC (rev 129592)
@@ -0,0 +1,9 @@
+include *.rst
+include *.txt
+include *.py
+include buildout.cfg
+include tox.ini
+
+recursive-include src *
+
+global-exclude *.pyc

Modified: zope.pluggableauth/trunk/bootstrap.py
===================================================================
--- zope.pluggableauth/trunk/bootstrap.py	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/bootstrap.py	2013-02-21 21:39:29 UTC (rev 129592)
@@ -18,33 +18,148 @@
 use the -c option to specify an alternate configuration file.
 """
 
-import os, shutil, sys, tempfile, urllib2
+import os, shutil, sys, tempfile
+from optparse import OptionParser
 
 tmpeggs = tempfile.mkdtemp()
 
-ez = {}
-exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
-                     ).read() in ez
-ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+usage = '''\
+[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
 
-import pkg_resources
+Bootstraps a buildout-based project.
 
-cmd = 'from setuptools.command.easy_install import main; main()'
-if sys.platform == 'win32':
-    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+Simply run this script in a directory containing a buildout.cfg, using the
+Python that you want bin/buildout to use.
 
-ws = pkg_resources.working_set
-assert os.spawnle(
-    os.P_WAIT, sys.executable, sys.executable,
-    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
-    dict(os.environ,
-         PYTHONPATH=
-         ws.find(pkg_resources.Requirement.parse('setuptools')).location
-         ),
-    ) == 0
+Note that by using --setup-source and --download-base to point to
+local resources, you can keep this script from going over the network.
+'''
 
+parser = OptionParser(usage=usage)
+parser.add_option("-v", "--version", help="use a specific zc.buildout version")
+
+parser.add_option("-t", "--accept-buildout-test-releases",
+                  dest='accept_buildout_test_releases',
+                  action="store_true", default=False,
+                  help=("Normally, if you do not specify a --version, the "
+                        "bootstrap script and buildout gets the newest "
+                        "*final* versions of zc.buildout and its recipes and "
+                        "extensions for you.  If you use this flag, "
+                        "bootstrap and buildout will get the newest releases "
+                        "even if they are alphas or betas."))
+parser.add_option("-c", "--config-file",
+                   help=("Specify the path to the buildout configuration "
+                         "file to be used."))
+parser.add_option("-f", "--find-links",
+                   help=("Specify a URL to search for buildout releases"))
+
+
+options, args = parser.parse_args()
+
+######################################################################
+# load/install distribute
+
+to_reload = False
+try:
+    import pkg_resources, setuptools
+    if not hasattr(pkg_resources, '_distribute'):
+        to_reload = True
+        raise ImportError
+except ImportError:
+    ez = {}
+
+    try:
+        from urllib.request import urlopen
+    except ImportError:
+        from urllib2 import urlopen
+
+    exec(urlopen('http://python-distribute.org/distribute_setup.py').read(), ez)
+    setup_args = dict(to_dir=tmpeggs, download_delay=0, no_fake=True)
+    ez['use_setuptools'](**setup_args)
+
+    if to_reload:
+        reload(pkg_resources)
+    import pkg_resources
+    # This does not (always?) update the default working set.  We will
+    # do it.
+    for path in sys.path:
+        if path not in pkg_resources.working_set.entries:
+            pkg_resources.working_set.add_entry(path)
+
+######################################################################
+# Install buildout
+
+ws  = pkg_resources.working_set
+
+cmd = [sys.executable, '-c',
+       'from setuptools.command.easy_install import main; main()',
+       '-mZqNxd', tmpeggs]
+
+find_links = os.environ.get(
+    'bootstrap-testing-find-links',
+    options.find_links or
+    ('http://downloads.buildout.org/'
+     if options.accept_buildout_test_releases else None)
+    )
+if find_links:
+    cmd.extend(['-f', find_links])
+
+distribute_path = ws.find(
+    pkg_resources.Requirement.parse('distribute')).location
+
+requirement = 'zc.buildout'
+version = options.version
+if version is None and not options.accept_buildout_test_releases:
+    # Figure out the most recent final version of zc.buildout.
+    import setuptools.package_index
+    _final_parts = '*final-', '*final'
+    def _final_version(parsed_version):
+        for part in parsed_version:
+            if (part[:1] == '*') and (part not in _final_parts):
+                return False
+        return True
+    index = setuptools.package_index.PackageIndex(
+        search_path=[distribute_path])
+    if find_links:
+        index.add_find_links((find_links,))
+    req = pkg_resources.Requirement.parse(requirement)
+    if index.obtain(req) is not None:
+        best = []
+        bestv = None
+        for dist in index[req.project_name]:
+            distv = dist.parsed_version
+            if _final_version(distv):
+                if bestv is None or distv > bestv:
+                    best = [dist]
+                    bestv = distv
+                elif distv == bestv:
+                    best.append(dist)
+        if best:
+            best.sort()
+            version = best[-1].version
+if version:
+    requirement = '=='.join((requirement, version))
+cmd.append(requirement)
+
+import subprocess
+if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=distribute_path)) != 0:
+    raise Exception(
+        "Failed to execute command:\n%s",
+        repr(cmd)[1:-1])
+
+######################################################################
+# Import and run buildout
+
 ws.add_entry(tmpeggs)
-ws.require('zc.buildout')
+ws.require(requirement)
 import zc.buildout.buildout
-zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+
+if not [a for a in args if '=' not in a]:
+    args.append('bootstrap')
+
+# if -c was provided, we push it back into args for buildout' main function
+if options.config_file is not None:
+    args[0:0] = ['-c', options.config_file]
+
+zc.buildout.buildout.main(args)
 shutil.rmtree(tmpeggs)

Modified: zope.pluggableauth/trunk/buildout.cfg
===================================================================
--- zope.pluggableauth/trunk/buildout.cfg	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/buildout.cfg	2013-02-21 21:39:29 UTC (rev 129592)
@@ -1,7 +1,26 @@
 [buildout]
 develop = .
+find-links =
+    ${buildout:directory}/ZODB-4.0.0dev.tar.gz
 parts = test
+versions = versions
 
 [test]
 recipe = zc.recipe.testrunner
 eggs = zope.pluggableauth [test]
+
+[versions]
+ZODB = 4.0.0dev
+zope.authentication = 4.1.0
+zope.container = 4.0.0a1
+zope.contenttype = 4.0.1
+zope.i18n = 4.0.0a4
+zope.location = 4.0.1
+zope.password = 4.0.0
+zope.publisher = 4.0.0a1
+zope.security = 4.0.0a3
+zope.session = 4.0.0a1
+zope.site = 4.0.0a1
+zope.tal = 4.0.0a1
+zope.traversing = 4.0.0a1
+

Modified: zope.pluggableauth/trunk/setup.py
===================================================================
--- zope.pluggableauth/trunk/setup.py	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/setup.py	2013-02-21 21:39:29 UTC (rev 129592)
@@ -27,54 +27,64 @@
 def read(*rnames):
     return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
 
-setup(name='zope.pluggableauth',
-      version='2.0dev',
-      author='Zope Foundation and Contributors',
-      author_email='zope-dev at zope.org',
-      description='Pluggable Authentication Utility',
-      long_description= "\n".join((
-        read('README.txt'),
-        '.. contents::\n\n',
-        read('CHANGES.txt'),
-        read('src', 'zope', 'pluggableauth', 'README.txt'),
-        )),
-      url='http://pypi.python.org/pypi/zope.pluggableauth',
-      license='ZPL 2.1',
-      keywords='zope3 ztk authentication pluggable',
-      packages=find_packages('src'),
-      package_dir = {'': 'src'},
-      namespace_packages=['zope'],
-      include_package_data = True,
-      zip_safe = False,
-      extras_require=dict(test=['zope.component[test]']),
-      install_requires=[
-          'ZODB3',
-          'setuptools',
-          'zope.authentication',
-          'zope.component',
-          'zope.container',
-          'zope.event',
-          'zope.i18nmessageid',
-          'zope.interface',
-          'zope.password >= 3.5.1',
-          'zope.publisher>=3.12',
-          'zope.schema',
-          'zope.security',
-          'zope.session',
-          'zope.site',
-          'zope.traversing',
-          ],
-     classifiers = [
-          'Development Status :: 5 - Production/Stable',
-          'Environment :: Web Environment',
-          'Intended Audience :: Developers',
-          'License :: OSI Approved :: Zope Public License',
-          'Programming Language :: Python',
-          'Programming Language :: Python :: 2',
-          'Programming Language :: Python :: 2.6',
-          'Programming Language :: Python :: 2.7',
-          'Natural Language :: English',
-          'Operating System :: OS Independent',
-          'Topic :: Internet :: WWW/HTTP',
-          'Framework :: Zope3'],
-      )
+setup(
+    name='zope.pluggableauth',
+    version='2.0.0a1.dev',
+    author='Zope Foundation and Contributors',
+    author_email='zope-dev at zope.org',
+    description='Pluggable Authentication Utility',
+    long_description= "\n".join((
+            read('README.txt'),
+            '.. contents::\n\n',
+            read('CHANGES.txt'),
+            read('src', 'zope', 'pluggableauth', 'README.txt'),
+            )),
+    url='http://pypi.python.org/pypi/zope.pluggableauth',
+    license='ZPL 2.1',
+    keywords='zope3 ztk authentication pluggable',
+    classifiers = [
+        'Development Status :: 5 - Production/Stable',
+        'Environment :: Web Environment',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: Zope Public License',
+        'Programming Language :: Python',
+        'Programming Language :: Python :: 2',
+        'Programming Language :: Python :: 2.6',
+        'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: 3',
+        'Programming Language :: Python :: 3.3',
+        'Programming Language :: Python :: Implementation :: CPython',
+        'Natural Language :: English',
+        'Operating System :: OS Independent',
+        'Topic :: Internet :: WWW/HTTP',
+        'Framework :: Zope3'],
+    packages=find_packages('src'),
+    package_dir = {'': 'src'},
+    namespace_packages=['zope'],
+    extras_require=dict(test=[
+            'zope.testing',
+            #'zope.component[test]' # Pulls in ZODB3 right now. :-(
+            ]),
+    install_requires=[
+        'persistent',
+        'setuptools',
+        'transaction',
+        'zope.authentication',
+        'zope.component',
+        'zope.container',
+        'zope.event',
+        'zope.i18nmessageid',
+        'zope.interface',
+        'zope.password >= 3.5.1',
+        'zope.publisher>=3.12',
+        'zope.schema',
+        'zope.security',
+        'zope.session',
+        'zope.site',
+        'zope.traversing',
+        ],
+    tests_include=['zope.testing'],
+    test_suite='zope.pluggableauth.tests.test_suite',
+    include_package_data = True,
+    zip_safe = False,
+    )

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/README.txt
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/README.txt	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/README.txt	2013-02-21 21:39:29 UTC (rev 129592)
@@ -124,13 +124,13 @@
 We can now use the PAU to authenticate a sample request::
 
   >>> from zope.publisher.browser import TestRequest
-  >>> print pau.authenticate(TestRequest())
+  >>> print(pau.authenticate(TestRequest()))
   None
 
 In this case, we cannot authenticate an empty request. In the same way, we
 will not be able to authenticate a request with the wrong credentials::
 
-  >>> print pau.authenticate(TestRequest(credentials='let me in!'))
+  >>> print(pau.authenticate(TestRequest(credentials='let me in!')))
   None
 
 However, if we provide the proper credentials::
@@ -174,7 +174,7 @@
 
 If neither plugins can authenticate, pau returns None::
 
-  >>> print pau.authenticate(TestRequest(credentials='let me in!!'))
+  >>> print(pau.authenticate(TestRequest(credentials='let me in!!')))
   None
 
 When we change the order of the authenticator plugins::

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/factories.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/factories.py	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/factories.py	2013-02-21 21:39:29 UTC (rev 129592)
@@ -166,7 +166,7 @@
             stack = [iter(self.groups)]
             while stack:
                 try:
-                    group_id = stack[-1].next()
+                    group_id = next(stack[-1])
                 except StopIteration:
                     stack.pop()
                 else:

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/ftpplugins.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/ftpplugins.py	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/ftpplugins.py	2013-02-21 21:39:29 UTC (rev 129592)
@@ -30,21 +30,25 @@
         Note the path is a required in the envirnoment.
 
           >>> from zope.publisher.ftp import FTPRequest
-          >>> from StringIO import StringIO
+          >>> try:
+          ...     from StringIO import StringIO
+          ... except ImportError:
+          ...     from io import StringIO
           >>> request = FTPRequest(StringIO(''),
-          ...                      {'credentials': ('bob', '123'),
+          ...                      {'credentials': (b'bob', b'123'),
           ...                       'path': '/a/b/c'})
 
         Now we create the plugin and get the credentials.
 
           >>> plugin = FTPCredentialsPlugin()
-          >>> plugin.extractCredentials(request)
+          >>> from pprint import pprint
+          >>> pprint(plugin.extractCredentials(request))
           {'login': u'bob', 'password': u'123'}
 
         This only works for FTPRequests.
 
           >>> from zope.publisher.base import TestRequest
-          >>> print plugin.extractCredentials(TestRequest('/'))
+          >>> print(plugin.extractCredentials(TestRequest('/')))
           None
 
         """

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/generic.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/generic.py	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/generic.py	2013-02-21 21:39:29 UTC (rev 129592)
@@ -72,7 +72,7 @@
 
     the plugin challenge will return None:
 
-      >>> print challenger.challenge(request)
+      >>> print(challenger.challenge(request))
       None
 
     signaling the PAU that it should try the next plugin for a challenge. If

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/groupfolder.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/groupfolder.py	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/groupfolder.py	2013-02-21 21:39:29 UTC (rev 129592)
@@ -140,13 +140,12 @@
     def description(self):
         return self._information.description
 
-    @apply
-    def members():
-        def get(self):
+    @property
+    def members(self):
             return self._information.principals
-        def set(self, value):
-            self._information.principals = value
-        return property(get, set)
+    @members.setter
+    def members(self, value):
+        self._information.principals = value
 
     def __repr__(self):
         return 'GroupInfo(%r)' % self.id
@@ -297,7 +296,7 @@
             if check:
                 try:
                     principalsUtility = component.getUtility(IAuthentication)
-                    nocycles(new, [], principalsUtility.getPrincipal)
+                    nocycles(sorted(new), [], principalsUtility.getPrincipal)
                 except GroupCycle:
                     # abort
                     self.setPrincipals(old, False)

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/groupfolder.txt
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/groupfolder.txt	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/groupfolder.txt	2013-02-21 21:39:29 UTC (rev 129592)
@@ -187,8 +187,8 @@
   ... # doctest: +NORMALIZE_WHITESPACE
   Traceback (most recent call last):
   ...
-  GroupCycle: (u'auth.group.G1',
-               ['auth.p2', u'auth.group.G1', u'auth.group.G2'])
+  GroupCycle: (u'auth.group.G2',
+               [u'auth.group.G2', u'auth.group.G1'])
 
 Trying to do so does not fire an event.
 

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/httpplugins.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/httpplugins.py	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/httpplugins.py	2013-02-21 21:39:29 UTC (rev 129592)
@@ -21,6 +21,11 @@
 from zope.schema import TextLine
 from zope.pluggableauth import interfaces
 
+try:
+    unicode
+except NameError:
+    # Py3: define unicode
+    unicode = str
 
 class IHTTPBasicAuthRealm(Interface):
     """HTTP Basic Auth Realm
@@ -53,25 +58,26 @@
         Now create the plugin and get the credentials.
 
           >>> plugin = HTTPBasicAuthCredentialsPlugin()
-          >>> plugin.extractCredentials(request)
+          >>> from pprint import pprint
+          >>> pprint(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())
+          >>> print(plugin.extractCredentials(TestRequest()))
           None
 
         Also, this plugin can *only* handle basic authentication.
 
           >>> request = TestRequest(environ={'HTTP_AUTHORIZATION': 'foo bar'})
-          >>> print plugin.extractCredentials(TestRequest())
+          >>> print(plugin.extractCredentials(TestRequest()))
           None
 
         This plugin only works with HTTP requests.
 
           >>> from zope.publisher.base import TestRequest
-          >>> print plugin.extractCredentials(TestRequest('/'))
+          >>> print(plugin.extractCredentials(TestRequest('/')))
           None
 
         """
@@ -81,7 +87,10 @@
         if request._auth:
             if request._auth.lower().startswith(u'basic '):
                 credentials = request._auth.split()[-1]
-                login, password = base64.decodestring(credentials).split(':')
+                if isinstance(credentials, unicode):
+                    # No encoding needed, should be base64 string anyways.
+                    credentials = credentials.encode()
+                login, password = base64.b64decode(credentials).split(b':')
                 return {'login': login.decode('utf-8'),
                         'password': password.decode('utf-8')}
         return None
@@ -113,7 +122,7 @@
           >>> from zope.publisher.base import TestRequest
           >>> request = TestRequest('/')
           >>> response = request.response
-          >>> print plugin.challenge(request)
+          >>> print(plugin.challenge(request))
           False
 
         """

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/idpicker.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/idpicker.py	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/idpicker.py	2013-02-21 21:39:29 UTC (rev 129592)
@@ -77,14 +77,14 @@
         >>> try:
         ...     IdPicker({}).checkName(u'bob\xfa', None)
         ... except UserError, e:
-        ...     print e
+        ...     print(e)
         ...     # doctest: +NORMALIZE_WHITESPACE
         Ids must contain only printable 7-bit non-space ASCII characters
 
         >>> try:
         ...     IdPicker({}).checkName(u'big bob', None)
         ... except UserError, e:
-        ...     print e
+        ...     print(e)
         ...     # doctest: +NORMALIZE_WHITESPACE
         Ids must contain only printable 7-bit non-space ASCII characters
 

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/principalfolder.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/principalfolder.py	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/principalfolder.py	2013-02-21 21:39:29 UTC (rev 129592)
@@ -182,8 +182,8 @@
 
     schema = ISearchSchema
 
-    def __init__(self, prefix=''):
-        self.prefix = unicode(prefix)
+    def __init__(self, prefix=u''):
+        self.prefix = prefix
         super(PrincipalFolder, self).__init__()
         self.__id_by_login = self._newContainerData()
 
@@ -222,7 +222,7 @@
 
             >>> try:
             ...     pf.__setitem__(u'1', principal)
-            ... except DuplicateIDError, e:
+            ... except DuplicateIDError as e:
             ...     pass
             >>>
         """

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/principalfolder.txt
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/principalfolder.txt	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/principalfolder.txt	2013-02-21 21:39:29 UTC (rev 129592)
@@ -14,7 +14,7 @@
 and add them to a principal folder:
 
   >>> from zope.pluggableauth.plugins.principalfolder import PrincipalFolder
-  >>> principals = PrincipalFolder('principal.')
+  >>> principals = PrincipalFolder(u'principal.')
   >>> principals['p1'] = p1
   >>> principals['p2'] = p2
 
@@ -101,7 +101,7 @@
   >>> 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)))
+  >>> pprint(list(principals.search({'search': 'D'}, batch_size=5)), width=60)
   [u'principal.0',
    u'principal.1',
    u'principal.10',

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/session.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/session.py	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/plugins/session.py	2013-02-21 21:39:29 UTC (rev 129592)
@@ -18,7 +18,6 @@
 import persistent
 import transaction
 import zope.container.contained
-from urllib import urlencode
 
 from zope.interface import implementer, Interface
 from zope.schema import TextLine
@@ -29,6 +28,11 @@
 from zope.site import hooks
 from zope.pluggableauth.interfaces import ICredentialsPlugin
 
+try:
+    from urllib import urlencode
+except ImportError:
+    # Py3: Location change.
+    from urllib.parse import urlencode
 
 class ISessionCredentials(Interface):
     """Interface for storing and accessing credentials in a session.
@@ -130,31 +134,32 @@
       >>> from zope.pluggableauth.tests import sessionSetUp
       >>> from zope.publisher.browser import TestRequest
       >>> request = TestRequest()
-      >>> print plugin.extractCredentials(request)
+      >>> print(plugin.extractCredentials(request))
       None
 
     We must explicitly provide credentials once so the plugin can store
     them in a session:
 
       >>> request = TestRequest(login='scott', password='tiger')
-      >>> plugin.extractCredentials(request)
+      >>> from pprint import pprint
+      >>> pprint(plugin.extractCredentials(request))
       {'login': 'scott', 'password': 'tiger'}
 
     Subsequent requests now have access to the credentials even if they're
     not explicitly in the request:
 
-      >>> plugin.extractCredentials(TestRequest())
+      >>> pprint(plugin.extractCredentials(TestRequest()))
       {'login': 'scott', 'password': 'tiger'}
 
     We can always provide new credentials explicitly in the request:
 
-      >>> plugin.extractCredentials(TestRequest(
-      ...     login='harry', password='hirsch'))
+      >>> pprint(plugin.extractCredentials(TestRequest(
+      ...     login='harry', password='hirsch')))
       {'login': 'harry', 'password': 'hirsch'}
 
     and these will be used on subsequent requests:
 
-      >>> plugin.extractCredentials(TestRequest())
+      >>> pprint(plugin.extractCredentials(TestRequest()))
       {'login': 'harry', 'password': 'hirsch'}
 
     We can also change the fields from which the credentials are extracted:
@@ -169,14 +174,14 @@
 
     The plugin now extracts the credentials information from these new fields:
 
-      >>> plugin.extractCredentials(request)
+      >>> pprint(plugin.extractCredentials(request))
       {'login': 'luke', 'password': 'the_force'}
 
     Finally, we clear the session credentials using the logout method:
 
       >>> plugin.logout(TestRequest())
       True
-      >>> print plugin.extractCredentials(TestRequest())
+      >>> print(plugin.extractCredentials(TestRequest()))
       None
 
     Instances are persistent:

Modified: zope.pluggableauth/trunk/src/zope/pluggableauth/tests.py
===================================================================
--- zope.pluggableauth/trunk/src/zope/pluggableauth/tests.py	2013-02-21 19:48:17 UTC (rev 129591)
+++ zope.pluggableauth/trunk/src/zope/pluggableauth/tests.py	2013-02-21 21:39:29 UTC (rev 129592)
@@ -16,6 +16,7 @@
 __docformat__ = "reStructuredText"
 
 import doctest
+import re
 import unittest
 import zope.component
 from zope.component.interfaces import IComponentLookup
@@ -29,6 +30,7 @@
 from zope.session.http import CookieClientIdManager
 from zope.site.folder import rootFolder
 from zope.site.site import LocalSiteManager, SiteManagerAdapter
+from zope.testing import renormalizing
 from zope.traversing.interfaces import ITraversable
 from zope.traversing.testing import setUp
 import zope.component.eventtesting
@@ -39,6 +41,17 @@
     ClientId, Session, PersistentSessionDataContainer)
 
 
+checker = renormalizing.RENormalizing([
+    # Python 3 unicode removed the "u".
+    (re.compile("u('.*?')"),
+     r"\1"),
+    (re.compile('u(".*?")'),
+     r"\1"),
+    # Python 3 adds module name to exceptions.
+    (re.compile("zope.pluggableauth.plugins.groupfolder.GroupCycle"),
+     r"GroupCycle"),
+    ])
+
 @implementer(IClientId)
 class TestClientId(object):
 
@@ -122,22 +135,32 @@
         SSHAPasswordManager(), IPasswordManager, 'SSHA')
 
 def test_suite():
+    flags = doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE
     suite = unittest.TestSuite((
         unittest.makeSuite(NonHTTPSessionTestCase),
-        doctest.DocTestSuite('zope.pluggableauth.interfaces'),
-        doctest.DocTestSuite('zope.pluggableauth.plugins.generic'),
-        doctest.DocTestSuite('zope.pluggableauth.plugins.ftpplugins'),
-        doctest.DocTestSuite('zope.pluggableauth.plugins.httpplugins'),
+        doctest.DocTestSuite(
+                'zope.pluggableauth.interfaces',
+                checker=checker),
+        doctest.DocTestSuite(
+                'zope.pluggableauth.plugins.generic',
+                checker=checker),
+        doctest.DocTestSuite(
+                'zope.pluggableauth.plugins.ftpplugins',
+                checker=checker),
+        doctest.DocTestSuite(
+                'zope.pluggableauth.plugins.httpplugins',
+                checker=checker),
 
         doctest.DocTestSuite('zope.pluggableauth.plugins.principalfolder'),
         doctest.DocFileSuite(
             'plugins/principalfolder.txt',
-            setUp=setupPassword),
+            setUp=setupPassword, checker=checker),
 
         doctest.DocTestSuite('zope.pluggableauth.plugins.groupfolder'),
         doctest.DocFileSuite(
             'plugins/groupfolder.txt',
-            setUp=zope.component.eventtesting.setUp),
+            setUp=zope.component.eventtesting.setUp,
+            checker=checker, optionflags=flags),
 
         doctest.DocTestSuite(
             'zope.pluggableauth.plugins.session',

Added: zope.pluggableauth/trunk/tox.ini
===================================================================
--- zope.pluggableauth/trunk/tox.ini	                        (rev 0)
+++ zope.pluggableauth/trunk/tox.ini	2013-02-21 21:39:29 UTC (rev 129592)
@@ -0,0 +1,28 @@
+[tox]
+envlist =
+    py26,py27,py33
+
+[testenv]
+commands =
+    python setup.py test -q
+# without explicit deps, setup.py test will download a bunch of eggs into $PWD
+# (and it seems I can't use zope.dottedname[testing] here, so forget DRY)
+deps =
+    {toxinidir}/ZODB-4.0.0dev.tar.gz
+    persistent
+    setuptools
+    transaction
+    zope.authentication
+    zope.component[test]
+    zope.container>=4.0.0a1
+    zope.event
+    zope.i18n>=4.0.0a4
+    zope.i18nmessageid
+    zope.interface
+    zope.password>=4.0.0
+    zope.publisher>=4.0.0a1
+    zope.schema
+    zope.security>=4.0.0a3
+    zope.session>=4.0.0a1
+    zope.site>=4.0.0a1
+    zope.traversing>=4.0.0a1



More information about the checkins mailing list