[Checkins] SVN: zc.buildout/branches/python-3-2/ rebranch

Jim Fulton jim at zope.com
Thu Mar 17 13:47:40 EDT 2011


Log message for revision 121011:
  rebranch

Changed:
  U   zc.buildout/branches/python-3-2/bootstrap/bootstrap.py
  U   zc.buildout/branches/python-3-2/buildout.cfg
  U   zc.buildout/branches/python-3-2/dev.py
  U   zc.buildout/branches/python-3-2/src/zc/buildout/__init__.py
  U   zc.buildout/branches/python-3-2/src/zc/buildout/allowhosts.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/bootstrap.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/buildout.py
  U   zc.buildout/branches/python-3-2/src/zc/buildout/buildout.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/debugging.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/dependencylinks.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/download.py
  U   zc.buildout/branches/python-3-2/src/zc/buildout/download.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/downloadcache.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/easy_install.py
  U   zc.buildout/branches/python-3-2/src/zc/buildout/easy_install.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/extends-cache.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/repeatable.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/rmtree.py
  U   zc.buildout/branches/python-3-2/src/zc/buildout/runsetup.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/setup.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/testing.py
  U   zc.buildout/branches/python-3-2/src/zc/buildout/testrecipes.py
  U   zc.buildout/branches/python-3-2/src/zc/buildout/tests.py
  U   zc.buildout/branches/python-3-2/src/zc/buildout/testselectingpython.py
  U   zc.buildout/branches/python-3-2/src/zc/buildout/update.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/upgrading_distribute.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/virtualenv.txt
  U   zc.buildout/branches/python-3-2/src/zc/buildout/windows.txt
  U   zc.buildout/branches/python-3-2/z3c.recipe.scripts_/src/z3c/recipe/scripts/scripts.py
  U   zc.buildout/branches/python-3-2/z3c.recipe.scripts_/src/z3c/recipe/scripts/tests.py
  U   zc.buildout/branches/python-3-2/zc.recipe.egg_/src/zc/recipe/egg/custom.py
  U   zc.buildout/branches/python-3-2/zc.recipe.egg_/src/zc/recipe/egg/egg.py
  U   zc.buildout/branches/python-3-2/zc.recipe.egg_/src/zc/recipe/egg/selecting-python.txt

-=-
Modified: zc.buildout/branches/python-3-2/bootstrap/bootstrap.py
===================================================================
--- zc.buildout/branches/python-3-2/bootstrap/bootstrap.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/bootstrap/bootstrap.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -18,7 +18,9 @@
 use the -c option to specify an alternate configuration file.
 """
 
-import os, shutil, sys, tempfile, textwrap, urllib, urllib2, subprocess
+import os, shutil, sys, tempfile, textwrap
+import urllib.request, urllib.parse, urllib.error, urllib.request
+import urllib.error, urllib.parse, subprocess
 from optparse import OptionParser
 
 if sys.platform == 'win32':
@@ -32,13 +34,13 @@
 
 # See zc.buildout.easy_install._has_broken_dash_S for motivation and comments.
 stdout, stderr = subprocess.Popen(
-    [sys.executable, '-Sc',
+    [sys.executable, '-S', '-c',
      'try:\n'
-     '    import ConfigParser\n'
+     '    import pickle\n'
      'except ImportError:\n'
-     '    print 1\n'
+     '    print(1)\n'
      'else:\n'
-     '    print 0\n'],
+     '    print(0)\n'],
     stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
 has_broken_dash_S = bool(int(stdout.strip()))
 
@@ -50,8 +52,9 @@
     # We will restart with python -S.
     args = sys.argv[:]
     args[0:0] = [sys.executable, '-S']
-    args = map(quote, args)
+    args = list(map(quote, args))
     os.execv(sys.executable, args)
+
 # Now we are running with -S.  We'll get the clean sys.path, import site
 # because distutils will do it later, and then reset the path and clean
 # out any namespace packages from site-packages that might have been
@@ -59,7 +62,7 @@
 clean_path = sys.path[:]
 import site
 sys.path[:] = clean_path
-for k, v in sys.modules.items():
+for k, v in list(sys.modules.items()):
     if k in ('setuptools', 'pkg_resources') or (
         hasattr(v, '__path__') and
         len(v.__path__)==1 and
@@ -77,7 +80,7 @@
     if value:
         if '://' not in value: # It doesn't smell like a URL.
             value = 'file://%s' % (
-                urllib.pathname2url(
+                urllib.request.pathname2url(
                     os.path.abspath(os.path.expanduser(value))),)
         if opt_str == '--download-base' and not value.endswith('/'):
             # Download base needs a trailing slash to make the world happy.
@@ -103,7 +106,8 @@
 parser.add_option("-v", "--version", dest="version",
                           help="use a specific zc.buildout version")
 parser.add_option("-d", "--distribute",
-                   action="store_true", dest="use_distribute", default=False,
+                   action="store_true", dest="use_distribute",
+                   default= sys.version_info[0] >= 3,
                    help="Use Distribute rather than Setuptools.")
 parser.add_option("--setup-source", action="callback", dest="setup_source",
                   callback=normalize_to_url, nargs=1, type="string",
@@ -160,10 +164,10 @@
     if not hasattr(pkg_resources, '_distribute'):
         raise ImportError
 except ImportError:
-    ez_code = urllib2.urlopen(
+    ez_code = urllib.request.urlopen(
         options.setup_source).read().replace('\r\n', '\n')
     ez = {}
-    exec ez_code in ez
+    exec(ez_code, ez)
     setup_args = dict(to_dir=eggs_dir, download_delay=0)
     if options.download_base:
         setup_args['download_base'] = options.download_base
@@ -247,9 +251,9 @@
 if exitcode != 0:
     sys.stdout.flush()
     sys.stderr.flush()
-    print ("An error occurred when trying to install zc.buildout. "
-           "Look above this message for any errors that "
-           "were output by easy_install.")
+    print("An error occurred when trying to install zc.buildout. "
+          "Look above this message for any errors that "
+          "were output by easy_install.")
     sys.exit(exitcode)
 
 ws.add_entry(eggs_dir)

Modified: zc.buildout/branches/python-3-2/buildout.cfg
===================================================================
--- zc.buildout/branches/python-3-2/buildout.cfg	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/buildout.cfg	2011-03-17 17:47:39 UTC (rev 121011)
@@ -1,9 +1,9 @@
 [buildout]
-develop = zc.recipe.egg_ z3c.recipe.scripts_ .
-parts = test oltest py
+develop = zc.recipe.egg_ z3c.recipe.scripts_ . testing
+parts = py test oltest
 
 [py]
-recipe = z3c.recipe.scripts
+recipe = zc.recipe.egg
 eggs = zc.buildout
        zope.testing
 interpreter = py

Modified: zc.buildout/branches/python-3-2/dev.py
===================================================================
--- zc.buildout/branches/python-3-2/dev.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/dev.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -15,11 +15,10 @@
 
 This is different from a normal bootstrapping process because the
 buildout egg itself is installed as a develop egg.
-
-$Id$
 """
 
-import os, shutil, sys, subprocess, urllib2, subprocess
+import os, shutil, sys, subprocess
+import urllib.request, urllib.error, urllib.parse
 from optparse import OptionParser
 
 if sys.platform == 'win32':
@@ -33,7 +32,7 @@
 
 # Detect https://bugs.launchpad.net/virtualenv/+bug/572545 .
 has_broken_dash_S = subprocess.call(
-    [sys.executable, '-Sc', 'import ConfigParser'])
+    [sys.executable, '-S', '-c', 'import pickle'])
 
 # In order to be more robust in the face of system Pythons, we want to
 # run without site-packages loaded.  This is somewhat tricky, in
@@ -43,7 +42,7 @@
     # We will restart with python -S.
     args = sys.argv[:]
     args[0:0] = [sys.executable, '-S']
-    args = map(quote, args)
+    args = list(map(quote, args))
     os.execv(sys.executable, args)
 # Now we are running with -S.  We'll get the clean sys.path, import site
 # because distutils will do it later, and then reset the path and clean
@@ -52,7 +51,7 @@
 clean_path = sys.path[:]
 import site
 sys.path[:] = clean_path
-for k, v in sys.modules.items():
+for k, v in list(sys.modules.items()):
     if (hasattr(v, '__path__') and
         len(v.__path__)==1 and
         not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))):
@@ -75,11 +74,11 @@
 
 parser = OptionParser(usage=usage)
 parser.add_option("-d", "--distribute",
-                   action="store_true", dest="use_distribute", default=False,
-                   help="Use Distribute rather than Setuptools.")
+                  action="store_true", dest="use_distribute",
+                  default=sys.version_info[0] >= 3,
+                  help="Use Distribute rather than Setuptools.")
 
 options, args = parser.parse_args()
-
 if args:
     parser.error('This script accepts no arguments other than its options.')
 
@@ -102,9 +101,10 @@
         raise ImportError
     import setuptools # A flag.  Sometimes pkg_resources is installed alone.
 except ImportError:
-    ez_code = urllib2.urlopen(setup_source).read().replace('\r\n', '\n')
+    ez_code = urllib.request.urlopen(setup_source).read().replace(
+        '\r\n'.encode(), '\n'.encode())
     ez = {}
-    exec ez_code in ez
+    exec(ez_code, ez)
     setup_args = dict(to_dir='eggs', download_delay=0)
     if options.use_distribute:
         setup_args['no_fake'] = True

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/__init__.py
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/__init__.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/__init__.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -12,13 +12,8 @@
 #
 ##############################################################################
 """Buildout package
-
-$Id$
 """
 
 class UserError(Exception):
     """Errors made by a user 
     """
-
-    def __str__(self):
-        return " ".join(map(str, self))

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/allowhosts.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/allowhosts.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/allowhosts.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -55,7 +55,7 @@
 
 Now we can run the buildout and make sure all attempts to dist.plone.org fails::
 
-    >>> print system(buildout) # doctest: +ELLIPSIS
+    >>> run(buildout) # doctest: +ELLIPSIS
     Develop: '/sample-buildout/allowdemo'
     ...
     Link to http://dist.plone.org ***BLOCKED*** by --allow-hosts
@@ -64,7 +64,6 @@
       Installing eggs.
       Getting distribution for 'kss.core'.
     Error: Couldn't find a distribution for 'kss.core'.
-    <BLANKLINE>
 
 That's what we wanted : this will prevent any attempt to access
 unwanted domains. For instance, some packages are listing in their
@@ -88,7 +87,7 @@
 
 Now we can run the buildout and make sure all attempts to dist.plone.org fails::
 
-    >>> print system(buildout) # doctest: +ELLIPSIS
+    >>> run(buildout) # doctest: +ELLIPSIS
     Develop: '/sample-buildout/allowdemo'
     ...
     Link to http://dist.plone.org ***BLOCKED*** by --allow-hosts
@@ -97,7 +96,6 @@
       Installing eggs.
       Getting distribution for 'kss.core'.
     Error: Couldn't find a distribution for 'kss.core'.
-    <BLANKLINE>
 
 Test for issues
 ---------------
@@ -115,12 +113,11 @@
     ... eggs=zc.buildout
     ... interpreter=python
     ... ''')
-    >>> print system(buildout)
+    >>> run(buildout)
     Unused options for buildout: 'foo'.
     Installing python.
     Generated script '/sample-buildout/bin/buildout'.
     Generated interpreter '/sample-buildout/bin/python'.
-    <BLANKLINE>
 
 The bug 239212 above would have got us an *AttributeError* on *buildout._allow_hosts*.
 This was fixed in this changeset:

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/bootstrap.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/bootstrap.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/bootstrap.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -20,9 +20,9 @@
     ... parts =
     ... ''')
     >>> write('bootstrap.py', open(bootstrap_py).read())
-    >>> print 'X'; print system(
+    >>> print('X'); run(
     ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
-    ...     'bootstrap.py'); print 'X' # doctest: +ELLIPSIS
+    ...     'bootstrap.py'); print('X') # doctest: +ELLIPSIS
     X...
     Creating directory '/sample/bin'.
     Creating directory '/sample/parts'.
@@ -43,7 +43,7 @@
     >>> ls(sample_buildout, 'bin')
     -  buildout
 
-    >>> print 'X'; ls(sample_buildout, 'eggs') # doctest: +ELLIPSIS
+    >>> print('X'); ls(sample_buildout, 'eggs') # doctest: +ELLIPSIS
     X...
     d  zc.buildout-...egg
 
@@ -53,7 +53,7 @@
     >>> buildout_script = join(sample_buildout, 'bin', 'buildout')
     >>> if sys.platform.startswith('win'):
     ...     buildout_script += '-script.py'
-    >>> print open(buildout_script).read() # doctest: +ELLIPSIS
+    >>> print(open(buildout_script).read()) # doctest: +ELLIPSIS
     #...
     <BLANKLINE>
     import sys
@@ -82,7 +82,7 @@
 
     >>> buildout_site_py = join(
     ...     sample_buildout, 'parts', 'buildout', 'site.py')
-    >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS
+    >>> print(open(buildout_site_py).read()) # doctest: +ELLIPSIS
     "...
         buildout_paths = [
             '/sample/eggs/setuptools-...egg',
@@ -102,7 +102,7 @@
     >>> ignored = system(
     ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
     ...     'bootstrap.py --accept-buildout-test-releases')
-    >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS
+    >>> print(open(buildout_site_py).read()) # doctest: +ELLIPSIS
     "...
         buildout_paths = [
             '/sample/eggs/setuptools-...egg',
@@ -115,7 +115,7 @@
 The buildout script remembers the decision to accept early releases, and
 alerts the user.
 
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
     ... # doctest: +NORMALIZE_WHITESPACE
     NOTE: Accepting early releases of build system packages.  Rerun bootstrap
           without --accept-buildout-test-releases (-t) to return to default
@@ -123,11 +123,11 @@
 
 This is accomplished within the script itself.
 
-    >>> print open(buildout_script).read() # doctest: +ELLIPSIS
+    >>> print(open(buildout_script).read()) # doctest: +ELLIPSIS
     #...
     sys.argv.insert(1, 'buildout:accept-buildout-test-releases=true')
-    print ('NOTE: Accepting early releases of build system packages.  Rerun '
-           'bootstrap without --accept-buildout-test-releases (-t) to return to '
+    print('NOTE: Accepting early releases of build system packages.  Rerun '
+          'bootstrap without --accept-buildout-test-releases (-t) to return to '
            'default behavior.')
     ...
 
@@ -137,7 +137,7 @@
     >>> ignored = system(
     ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
     ...     'bootstrap.py')
-    >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS
+    >>> print(open(buildout_site_py).read()) # doctest: +ELLIPSIS
     "...
         buildout_paths = [
             '/sample/eggs/setuptools-...egg',
@@ -153,9 +153,9 @@
 
 Let's try with an unknown version::
 
-    >>> print 'XX'; print system(
+    >>> print('XX'); run(
     ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
-    ...     'bootstrap.py --version UNKNOWN'); print 'X' # doctest: +ELLIPSIS
+    ...     'bootstrap.py --version UNKNOWN'); print('X') # doctest: +ELLIPSIS
     ...
     X...
     No local packages or download links found for zc.buildout==UNKNOWN...
@@ -163,9 +163,9 @@
 
 Now let's try with `1.1.2`, which happens to exist::
 
-    >>> print 'X'; print system(
+    >>> print('X'); run(
     ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
-    ...     'bootstrap.py --version 1.1.2'); print 'X'
+    ...     'bootstrap.py --version 1.1.2'); print('X')
     ...
     X
     Generated script '/sample/bin/buildout'.
@@ -175,7 +175,7 @@
 Versions older than 1.5.0 put their egg dependencies in the ``buildout`` script.
 Let's make sure it was generated as we expect::
 
-    >>> print open(buildout_script).read() # doctest: +ELLIPSIS
+    >>> print(open(buildout_script).read()) # doctest: +ELLIPSIS
     #...
     <BLANKLINE>
     import sys
@@ -192,9 +192,9 @@
 
 Let's try with `1.2.1`::
 
-    >>> print 'X'; print system(
+    >>> print('X'); run(
     ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
-    ...     'bootstrap.py --version 1.2.1'); print 'X' # doctest: +ELLIPSIS
+    ...     'bootstrap.py --version 1.2.1'); print('X') # doctest: +ELLIPSIS
     ...
     X
     Generated script '/sample/bin/buildout'.
@@ -203,7 +203,7 @@
 
 Let's make sure the generated ``buildout`` script uses it::
 
-    >>> print open(buildout_script).read() # doctest: +ELLIPSIS
+    >>> print(open(buildout_script).read()) # doctest: +ELLIPSIS
     #...
     <BLANKLINE>
     import sys
@@ -221,14 +221,14 @@
 ``zc.buildout`` now can also run with `Distribute` with the `--distribute`
 option::
 
-    >>> print 'XX'; print system(
+    >>> print('XX'); run(
     ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
     ...     'bootstrap.py --distribute') # doctest: +ELLIPSIS
     ...
     X...Generated script '/sample/bin/buildout'...
 
 Let's make sure the generated ``site.py`` uses it::
-    >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS
+    >>> print(open(buildout_site_py).read()) # doctest: +ELLIPSIS
     "...
         buildout_paths = [
             '/sample/eggs/distribute-...egg',
@@ -238,7 +238,7 @@
 
 Make sure both options can be used together::
 
-    >>> print 'XX'; print system(
+    >>> print('XX'); run(
     ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
     ...     'bootstrap.py --distribute --version 1.2.1')
     ... # doctest: +ELLIPSIS
@@ -247,7 +247,7 @@
 Let's make sure the old-style generated ``buildout`` script uses
 ``Distribute`` *and* ``zc.buildout-1.2.1``::
 
-    >>> print open(buildout_script).read() # doctest: +ELLIPSIS
+    >>> print(open(buildout_script).read()) # doctest: +ELLIPSIS
     #...
     <BLANKLINE>
     import sys
@@ -268,7 +268,7 @@
     >>> f = open(conf_file, 'w')
     >>> f.write('[buildout]\nparts=\n\n')
     >>> f.close()
-    >>> print 'XX'; print system(
+    >>> print('XX'); run(
     ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
     ...     'bootstrap.py -c %s --distribute' % conf_file) # doctest: +ELLIPSIS
     X...Generated script '/sample/bin/buildout'...
@@ -283,32 +283,27 @@
     ...     pprint.pprint(kwargs, width=40)
     ...     sys.exit()
     ... ''')
-    >>> print system(
-    ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
+    >>> run(zc.buildout.easy_install._safe_arg(sys.executable)+' '+
     ...     'bootstrap.py --setup-source=./ez_setup.py')
     ... # doctest: +ELLIPSIS
     {'download_delay': 0,
      'to_dir': '...'}
-    <BLANKLINE>
 
 You can also pass a download-cache, and a place in which eggs should be stored
 (they are normally stored in a temporary directory).
 
-    >>> print system(
-    ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
+    >>> run(zc.buildout.easy_install._safe_arg(sys.executable)+' '+
     ...     'bootstrap.py --setup-source=./ez_setup.py '+
     ...     '--download-base=./download-cache --eggs=eggs')
     ... # doctest: +ELLIPSIS
     {'download_base': '/sample/download-cache/',
      'download_delay': 0,
      'to_dir': '/sample/eggs'}
-    <BLANKLINE>
 
 Here's the entire help text.
 
-    >>> print system(
-    ...     zc.buildout.easy_install._safe_arg(sys.executable)+' '+
-    ...     'bootstrap.py --help'),
+    >>> run(zc.buildout.easy_install._safe_arg(sys.executable)+' '+
+    ...     'bootstrap.py --help')
     ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
     Usage: [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
     <BLANKLINE>

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/buildout.py
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/buildout.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/buildout.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -14,14 +14,18 @@
 """Buildout main script
 """
 
-from rmtree import rmtree
+from .rmtree import rmtree
 try:
     from hashlib import md5
 except ImportError:
     # Python 2.4 and older
     from md5 import md5
 
-import ConfigParser
+try:
+    from UserDict import DictMixin
+except ImportError:
+    from collections import MutableMapping as DictMixin
+
 import copy
 import distutils.errors
 import glob
@@ -33,7 +37,6 @@
 import shutil
 import sys
 import tempfile
-import UserDict
 import warnings
 import subprocess
 import zc.buildout
@@ -43,8 +46,10 @@
 
 realpath = zc.buildout.easy_install.realpath
 
+setuptools_key = zc.buildout.easy_install.setuptools_key
+
 pkg_resources_loc = pkg_resources.working_set.find(
-    pkg_resources.Requirement.parse('setuptools')).location
+    pkg_resources.Requirement.parse(setuptools_key)).location
 
 _isurl = re.compile('([a-zA-Z0-9+.-]+)://').match
 
@@ -57,12 +62,15 @@
     """A required option was missing.
     """
 
+    def __str__(self):
+        return zc.buildout.UserError.__str__(self)
+
 class MissingSection(zc.buildout.UserError, KeyError):
     """A required section is missing.
     """
 
     def __str__(self):
-        return "The referenced section, %r, was not defined." % self[0]
+        return "The referenced section, %r, was not defined." % self.args[0]
 
 
 def _annotate_section(section, note):
@@ -76,20 +84,20 @@
     return data
 
 def _print_annotate(data):
-    sections = data.keys()
+    sections = list(data.keys())
     sections.sort()
-    print
-    print "Annotated sections"
-    print "="*len("Annotated sections")
+    print()
+    print("Annotated sections")
+    print("="*len("Annotated sections"))
     for section in sections:
-        print
-        print '[%s]' % section
-        keys = data[section].keys()
+        print()
+        print('[%s]' % section)
+        keys = list(data[section].keys())
         keys.sort()
         for key in keys:
             value, notes = data[section][key]
             keyvalue = "%s= %s" % (key, value)
-            print keyvalue
+            print(keyvalue)
             line = '   '
             for note in notes.split():
                 if note == '[+]':
@@ -97,9 +105,9 @@
                 elif note == '[-]':
                     line = '-= '
                 else:
-                    print line, note
+                    print(line, note)
                     line = '   '
-    print
+    print()
 
 
 def _unannotate_section(section):
@@ -141,7 +149,7 @@
     }, 'DEFAULT_VALUE')
 
 
-class Buildout(UserDict.DictMixin):
+class Buildout(DictMixin):
 
     def __init__(self, config_file, cloptions,
                  user_defaults=True, windows_restart=False, command=None):
@@ -159,7 +167,7 @@
             base = os.path.dirname(config_file)
             if not os.path.exists(config_file):
                 if command == 'init':
-                    print 'Creating %r.' % config_file
+                    print('Creating %r.' % config_file)
                     open(config_file, 'w').write('[buildout]\nparts = \n')
                 elif command == 'setup':
                     # Sigh. This model of a buildout instance
@@ -191,7 +199,8 @@
                                        '.buildout', 'default.cfg')
             if os.path.exists(user_config):
                 _update(data, _open(os.path.dirname(user_config), user_config,
-                                    [], data['buildout'].copy(), override, set()))
+                                    [], data['buildout'].copy(), override,
+                                    set()))
 
         # load configuration files
         if config_file:
@@ -344,7 +353,7 @@
 
         # Get a base working set for our distributions that corresponds to the
         # stated desires in the configuration.
-        distributions = ['setuptools', 'zc.buildout']
+        distributions = [setuptools_key, 'zc.buildout']
         if options.get('offline') == 'true':
             ws = zc.buildout.easy_install.working_set(
                 distributions, options['executable'],
@@ -366,7 +375,7 @@
 
         # Now copy buildout and setuptools eggs, and record destination eggs:
         entries = []
-        for name in 'setuptools', 'zc.buildout':
+        for name in setuptools_key, 'zc.buildout':
             r = pkg_resources.Requirement.parse(name)
             dist = ws.find(r)
             if dist.precedence == pkg_resources.DEVELOP_DIST:
@@ -470,13 +479,12 @@
         if self._log_level < logging.DEBUG:
             sections = list(self)
             sections.sort()
-            print
-            print 'Configuration data:'
+            print()
+            print('Configuration data:')
             for section in self._data:
                 _save_options(section, self[section], sys.stdout)
-            print
+            print()
 
-
         # compute new part recipe signatures
         self._compute_part_signatures(install_parts)
 
@@ -621,7 +629,7 @@
         installed = self['buildout']['installed']
         f = open(installed, 'a')
         f.write('\n[buildout]\n')
-        for option, value in buildout_options.items():
+        for option, value in list(buildout_options.items()):
             _save_option(option, value, f)
         f.close()
 
@@ -637,7 +645,7 @@
                 recipe, 'zc.buildout.uninstall', entry, self)
             self._logger.info('Running uninstall recipe.')
             uninstaller(part, installed_part_options[part])
-        except (ImportError, pkg_resources.DistributionNotFound), v:
+        except (ImportError, pkg_resources.DistributionNotFound) as v:
             pass
 
         # remove created files and directories
@@ -727,17 +735,16 @@
     def _read_installed_part_options(self):
         old = self['buildout']['installed']
         if old and os.path.isfile(old):
-            parser = ConfigParser.RawConfigParser()
-            parser.optionxform = lambda s: s
-            parser.read(old)
+            fp = open(old)
+            sections = _read(fp, old)
+            fp.close()
             result = {}
-            for section in parser.sections():
-                options = {}
-                for option, value in parser.items(section):
+            for section, options in sections.items():
+                for option, value in options.items():
                     if '%(' in value:
                         for k, v in _spacey_defaults:
                             value = value.replace(k, v)
-                    options[option] = value
+                        options[option] = value
                 result[section] = Options(self, section, options)
 
             return result, True
@@ -777,7 +784,7 @@
         installed = recipe_class(self, part, options).install()
         if installed is None:
             installed = []
-        elif isinstance(installed, basestring):
+        elif isinstance(installed, str):
             installed = [installed]
         base = self._buildout_path('')
         installed = [d.startswith(base) and d[len(base):] or d
@@ -792,7 +799,7 @@
         f = open(installed, 'w')
         _save_options('buildout', installed_options['buildout'], f)
         for part in installed_options['buildout']['parts'].split():
-            print >>f
+            print(file=f)
             _save_options(part, installed_options[part], f)
         f.close()
 
@@ -845,10 +852,7 @@
         options = self['buildout']
 
         specs = ['zc.buildout']
-        if zc.buildout.easy_install.is_distribute:
-            specs.append('distribute')
-        else:
-            specs.append('setuptools')
+        specs.append(setuptools_key)
         ws = zc.buildout.easy_install.install(
             [
             (spec + ' ' + options.get(spec+'-version', '')).strip()
@@ -863,7 +867,7 @@
             )
 
         upgraded = []
-        for project in 'zc.buildout', 'setuptools':
+        for project in 'zc.buildout', setuptools_key:
             req = pkg_resources.Requirement.parse(project)
             project_location = pkg_resources.working_set.find(req).location
             if ws.find(req).location != project_location:
@@ -889,7 +893,7 @@
             return
 
         if sys.platform == 'win32' and not self.__windows_restart:
-            args = map(zc.buildout.easy_install._safe_arg, sys.argv)
+            args = list(map(zc.buildout.easy_install._safe_arg, sys.argv))
             args.insert(1, '-W')
             if not __debug__:
                 args.insert(0, '-O')
@@ -939,7 +943,7 @@
             )
 
         # Restart
-        args = map(zc.buildout.easy_install._safe_arg, sys.argv)
+        args = list(map(zc.buildout.easy_install._safe_arg, sys.argv))
         if not __debug__:
             args.insert(0, '-O')
         args.insert(0, zc.buildout.easy_install._safe_arg(sys.executable))
@@ -1005,12 +1009,12 @@
         fd, tsetup = tempfile.mkstemp()
         exe = zc.buildout.easy_install._safe_arg(sys.executable)
         try:
-            os.write(fd, zc.buildout.easy_install.runsetup_template % dict(
+            os.write(fd, (zc.buildout.easy_install.runsetup_template % dict(
                 setuptools=pkg_resources_loc,
                 setupdir=os.path.dirname(setup),
                 setup=setup,
                 __file__ = setup,
-                ))
+                )).encode())
             if is_jython:
                 arg_list = list()
 
@@ -1056,11 +1060,13 @@
         raise NotImplementedError('__delitem__')
 
     def keys(self):
-        return self._raw.keys()
+        return list(self._raw.keys())
 
     def __iter__(self):
         return iter(self._raw)
 
+    def __len__(self):
+        return len(self._raw)
 
 def _install_and_load(spec, group, entry, buildout):
     __doing__ = 'Loading recipe %r.', spec
@@ -1093,7 +1099,7 @@
         return pkg_resources.load_entry_point(
             req.project_name, group, entry)
 
-    except Exception, v:
+    except Exception as v:
         buildout._logger.log(
             1,
             "Could't load %s entry point %s\nfrom %s:\n%s.",
@@ -1101,7 +1107,7 @@
         raise
 
 
-class Options(UserDict.DictMixin):
+class Options(DictMixin):
 
     def __init__(self, buildout, section, data):
         self.buildout = buildout
@@ -1118,7 +1124,7 @@
             self._raw = self._do_extend_raw(name, self._raw, [])
 
         # force substitutions
-        for k, v in self._raw.items():
+        for k, v in list(self._raw.items()):
             if '${' in v:
                 self._dosub(k, v)
 
@@ -1269,12 +1275,17 @@
         elif key in self._data:
             del self._data[key]
         else:
-            raise KeyError, key
+            raise KeyError(key)
 
     def keys(self):
         raw = self._raw
         return list(self._raw) + [k for k in self._data if k not in raw]
 
+    def __iter__(self):
+        return iter(self.keys())
+    def __len__(self):
+        return len(self.keys())
+
     def copy(self):
         result = self._raw.copy()
         result.update(self._cooked)
@@ -1371,11 +1382,11 @@
         value = '%(__buildout_space_n__)s' + value[2:]
     if value.endswith('\n\t'):
         value = value[:-2] + '%(__buildout_space_n__)s'
-    print >>f, option, '=', value
+    print(option, '=', value, file=f)
 
 def _save_options(section, options, f):
-    print >>f, '[%s]' % section
-    items = options.items()
+    print('[%s]' % section, file=f)
+    items = list(options.items())
     items.sort()
     for option, value in items:
         _save_option(option, value, f)
@@ -1421,25 +1432,17 @@
     root_config_file = not seen
     seen.append(filename)
 
-    result = {}
-
-    parser = ConfigParser.RawConfigParser()
-    parser.optionxform = lambda s: s
-    parser.readfp(fp)
+    result = _read(fp, filename)
+    fp.close()
     if is_temp:
-        fp.close()
         os.remove(path)
 
-    extends = None
-    for section in parser.sections():
-        options = dict(parser.items(section))
-        if section == 'buildout':
-            extends = options.pop('extends', extends)
-            if 'extended-by' in options:
-                raise zc.buildout.UserError(
-                    'No-longer supported "extended-by" option found in %s.' %
-                    filename)
-        result[section] = options
+    options = result.get('buildout', {})
+    extends = options.pop('extends', None)
+    if 'extended-by' in options:
+        raise zc.buildout.UserError(
+            'No-longer supported "extended-by" option found in %s.' %
+            filename)
 
     result = _annotate(result, filename)
 
@@ -1472,11 +1475,11 @@
                         if (not (f.endswith('pyc') or f.endswith('pyo'))
                             and os.path.exists(os.path.join(dirpath, f)))
                         ]
-        hash.update(' '.join(dirnames))
-        hash.update(' '.join(filenames))
+        hash.update(' '.join(dirnames).encode())
+        hash.update(' '.join(filenames).encode())
         for name in filenames:
-            hash.update(open(os.path.join(dirpath, name)).read())
-    _dir_hashes[dir] = dir_hash = hash.digest().encode('base64').strip()
+            hash.update(open(os.path.join(dirpath, name)).read().encode())
+    _dir_hashes[dir] = dir_hash = hash.hexdigest()
     return dir_hash
 
 def _dists_sig(dists):
@@ -1491,7 +1494,7 @@
 
 def _update_section(s1, s2):
     s2 = s2.copy() # avoid mutating the second argument, which is unexpected
-    for k, v in s2.items():
+    for k, v in list(s2.items()):
         v2, note2 = v
         if k.endswith('+'):
             key = k.rstrip(' +')
@@ -1565,9 +1568,9 @@
 
 _early_release_initialization_code = """\
 sys.argv.insert(1, 'buildout:accept-buildout-test-releases=true')
-print ('NOTE: Accepting early releases of build system packages.  Rerun '
-       'bootstrap without --accept-buildout-test-releases (-t) to return to '
-       'default behavior.')
+print('NOTE: Accepting early releases of build system packages.  Rerun '
+      'bootstrap without --accept-buildout-test-releases (-t) to return to '
+      'default behavior.')
 """
 
 _usage = """\
@@ -1690,7 +1693,7 @@
 
 """
 def _help():
-    print _usage
+    print(_usage)
     sys.exit(0)
 
 def main(args=None):
@@ -1754,7 +1757,7 @@
                         _error("No timeout value must be numeric", orig_op)
 
                     import socket
-                    print 'Setting socket time out to %d seconds' % timeout
+                    print('Setting socket time out to %d seconds' % timeout)
                     socket.setdefaulttimeout(timeout)
 
             elif op:
@@ -1795,15 +1798,16 @@
             _error('invalid command:', command)
     else:
         command = 'install'
-    
+
     try:
         try:
             buildout = Buildout(config_file, options,
                                 user_defaults, windows_restart, command)
             getattr(buildout, command)(args)
-        except Exception, v:
+        except Exception:
             _doing()
             exc_info = sys.exc_info()
+            v = exc_info[1]
             import pdb, traceback
             if debug:
                 traceback.print_exception(*exc_info)
@@ -1811,7 +1815,7 @@
                 pdb.post_mortem(exc_info[2])
             else:
                 if isinstance(v, (zc.buildout.UserError,
-                                  distutils.errors.DistutilsError,
+                                  distutils.errors.DistutilsError
                                   )
                               ):
                     _error(str(v))
@@ -1829,3 +1833,153 @@
         result = list(iterable);
         result.reverse()
         return result
+
+# The following copied from Python 2 config parser because:
+# - The py3 configparser isn't backward compatible
+# - Both strip option values in undesireable ways
+# - dict of dicts is a much simpler api
+
+
+class Error(Exception):
+    """Base class for ConfigParser exceptions."""
+
+    def _get_message(self):
+        """Getter for 'message'; needed only to override deprecation in
+        BaseException."""
+        return self.__message
+
+    def _set_message(self, value):
+        """Setter for 'message'; needed only to override deprecation in
+        BaseException."""
+        self.__message = value
+
+    # BaseException.message has been deprecated since Python 2.6.  To prevent
+    # DeprecationWarning from popping up over this pre-existing attribute, use
+    # a new property that takes lookup precedence.
+    message = property(_get_message, _set_message)
+
+    def __init__(self, msg=''):
+        self.message = msg
+        Exception.__init__(self, msg)
+
+    def __repr__(self):
+        return self.message
+
+class ParsingError(Error):
+    """Raised when a configuration file does not follow legal syntax."""
+
+    def __init__(self, filename):
+        Error.__init__(self, 'File contains parsing errors: %s' % filename)
+        self.filename = filename
+        self.errors = []
+
+    def append(self, lineno, line):
+        self.errors.append((lineno, line))
+        self.message += '\n\t[line %2d]: %s' % (lineno, line)
+
+class MissingSectionHeaderError(ParsingError):
+    """Raised when a key-value pair is found before any section header."""
+
+    def __init__(self, filename, lineno, line):
+        Error.__init__(
+            self,
+            'File contains no section headers.\nfile: %s, line: %d\n%r' %
+            (filename, lineno, line))
+        self.filename = filename
+        self.lineno = lineno
+        self.line = line
+
+SECTCRE = re.compile(
+    r'\['                                 # [
+    r'(?P<header>[^]]+)'                  # very permissive!
+    r'\]'                                 # ]
+    )
+OPTCRE = re.compile(
+    r'(?P<option>[^:=\s][^:=]*)'          # very permissive!
+    r'\s*(?P<vi>[:=])\s*'                 # any number of space/tab,
+                                          # followed by separator
+                                          # (either : or =), followed
+                                          # by any # space/tab
+    r'(?P<value>.*)$'                     # everything up to eol
+    )
+
+def _read(fp, fpname):
+    """Parse a sectioned setup file.
+
+    The sections in setup file contains a title line at the top,
+    indicated by a name in square brackets (`[]'), plus key/value
+    options lines, indicated by `name: value' format lines.
+    Continuations are represented by an embedded newline then
+    leading whitespace.  Blank lines, lines beginning with a '#',
+    and just about everything else are ignored.
+    """
+    _sections = {}
+    cursect = None                            # None, or a dictionary
+    optname = None
+    lineno = 0
+    e = None                                  # None, or an exception
+    while True:
+        line = fp.readline()
+        if not line:
+            break
+        lineno = lineno + 1
+        # comment or blank line?
+        if line.strip() == '' or line[0] in '#;':
+            continue
+        if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
+            # no leading whitespace
+            continue
+        # continuation line?
+        if line[0].isspace() and cursect is not None and optname:
+            value = line.strip()
+            if value:
+                cursect[optname] = "%s\n%s" % (cursect[optname], value)
+        # a section header or option header?
+        else:
+            # is it a section header?
+            mo = SECTCRE.match(line)
+            if mo:
+                sectname = mo.group('header')
+                if sectname in _sections:
+                    cursect = _sections[sectname]
+                else:
+                    cursect = {}
+                    _sections[sectname] = cursect
+                # So sections can't start with a continuation line
+                optname = None
+            # no section header in the file?
+            elif cursect is None:
+                raise MissingSectionHeaderError(fpname, lineno, line)
+            # an option line?
+            else:
+                mo = OPTCRE.match(line)
+                if mo:
+                    optname, vi, optval = mo.group('option', 'vi', 'value')
+                    # This check is fine because the OPTCRE cannot
+                    # match if it would set optval to None
+                    if optval is not None:
+                        if vi in ('=', ':') and ';' in optval:
+                            # ';' is a comment delimiter only if it follows
+                            # a spacing character
+                            pos = optval.find(';')
+                            if pos != -1 and optval[pos-1].isspace():
+                                optval = optval[:pos]
+                        optval = optval.strip()
+                    # allow empty values
+                    if optval == '""':
+                        optval = ''
+                    optname = optname.rstrip()
+                    cursect[optname] = optval
+                else:
+                    # a non-fatal parsing error occurred.  set up the
+                    # exception but keep going. the exception will be
+                    # raised at the end of the file and will contain a
+                    # list of all bogus lines
+                    if not e:
+                        e = ParsingError(fpname)
+                    e.append(lineno, repr(line))
+    # if any parsing errors occurred, raise an exception
+    if e:
+        raise e
+
+    return _sections

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/buildout.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/buildout.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/buildout.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -289,7 +289,7 @@
     >>> import os
     >>> os.chdir(sample_buildout)
     >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Installing data-dir.
     data-dir: Creating directory mystuff
@@ -338,7 +338,7 @@
     ... path = mydata
     ... """)
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling data-dir.
     Installing data-dir.
@@ -358,7 +358,7 @@
 the part will be reinstalled:
 
     >>> rmdir(sample_buildout, 'mydata')
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling data-dir.
     Installing data-dir.
@@ -389,7 +389,7 @@
 
 We'll get a user error, not a traceback.
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     data-dir: Cannot create /xxx/mydata. /xxx is not a directory.
     While:
@@ -454,7 +454,7 @@
     ... path = foo bin
     ... """)
 
-    >>> print system(buildout), # doctest: +ELLIPSIS
+    >>> run(buildout) # doctest: +ELLIPSIS
     Develop: '/sample-buildout/recipes'
     Uninstalling data-dir.
     Installing data-dir.
@@ -488,7 +488,7 @@
     ... path = foo bins
     ... """)
 
-    >>> print system(buildout), # doctest: +ELLIPSIS
+    >>> run(buildout) # doctest: +ELLIPSIS
     Develop: '/sample-buildout/recipes'
     Installing data-dir.
     data-dir: Creating directory foo
@@ -564,7 +564,7 @@
 
 When we rerun the buildout:
 
-    >>> print system(buildout), # doctest: +ELLIPSIS
+    >>> run(buildout) # doctest: +ELLIPSIS
     Develop: '/sample-buildout/recipes'
     Installing data-dir.
     data-dir: Creating directory foo
@@ -636,7 +636,8 @@
 
 ..
 
-    >>> remove(sample_buildout, 'recipes', 'mkdir.pyc')
+    >>> for (d, _, f) in os.walk(join(sample_buildout, 'recipes')):
+    ...     if f == 'mkdir.pyc': rermove(join(d, f))
 
 We returned by calling created, taking advantage of the fact that it
 returns the registered paths.  We did this for illustrative purposes.
@@ -645,7 +646,7 @@
 If we rerun the buildout, again, we'll get the error and no
 directories will be created:
 
-    >>> print system(buildout), # doctest: +ELLIPSIS
+    >>> run(buildout) # doctest: +ELLIPSIS
     Develop: '/sample-buildout/recipes'
     Installing data-dir.
     data-dir: Creating directory foo
@@ -675,7 +676,7 @@
     ... path = foo bins
     ... """)
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Installing data-dir.
     data-dir: Creating directory foo
@@ -722,7 +723,7 @@
 the origin of the value (file name or COMPUTED_VALUE, DEFAULT_VALUE,
 COMMAND_LINE_VALUE).
 
-    >>> print system(buildout+ ' annotate'),
+    >>> run(buildout+ ' annotate')
     ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
     <BLANKLINE>
     Annotated sections
@@ -808,10 +809,10 @@
     ...         self.options = options
     ...
     ...     def install(self):
-    ...         items = self.options.items()
+    ...         items = list(self.options.items())
     ...         items.sort()
     ...         for option, value in items:
-    ...             print option, value
+    ...             print(option, value)
     ...         return ()
     ...
     ...     update = install
@@ -867,7 +868,7 @@
 Now, if we run the buildout, we'll see the options with the values
 substituted.
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling data-dir.
     Installing data-dir.
@@ -886,7 +887,7 @@
 recipe, so it assumed it could and reinstalled mydata.  If we rerun
 the buildout:
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Updating data-dir.
     Updating debug.
@@ -925,7 +926,7 @@
     ... path = mydata
     ... """)
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling debug.
     Updating data-dir.
@@ -963,7 +964,7 @@
 
 It will still be treated as a part:
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling debug.
     Updating data-dir.
@@ -1002,7 +1003,7 @@
 
 It will still be treated as a part:
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Updating data-dir.
     Updating debug.
@@ -1051,7 +1052,7 @@
     ... path = mydata
     ... """)
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling debug.
     Uninstalling data-dir.
@@ -1143,8 +1144,8 @@
     >>> write(sample_buildout, 'demo', 'demo.py',
     ... """
     ... def ext(buildout):
-    ...     print [part['option'] for name, part in buildout.items() \
-    ...           if name.startswith('part')]
+    ...     print([part['option'] for name, part in buildout.items() \
+    ...           if name.startswith('part')])
     ... """)
 
     >>> write(sample_buildout, 'demo', 'setup.py',
@@ -1167,7 +1168,7 @@
     ... """)
 
     >>> os.chdir(sample_buildout)
-    >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
+    >>> run(os.path.join(sample_buildout, 'bin', 'buildout'))
     Develop: '/sample-buildout/demo'
     Uninstalling myfiles.
     Getting distribution for 'recipes'.
@@ -1185,14 +1186,14 @@
     ... extends = extension2.cfg
     ... """)
 
-    >>> print system(os.path.join('bin', 'buildout')),
+    >>> run(os.path.join('bin', 'buildout'))
     ['a1 a2/na3 a4/na5', 'b1 b2 b3 b4', 'c1 c2/nc3 c4 c5', 'h1 h2']
     Develop: '/sample-buildout/demo'
 
 Annotated sections output shows which files are responsible for which
 operations.
 
-    >>> print system(os.path.join('bin', 'buildout') + ' annotate'),
+    >>> run(os.path.join('bin', 'buildout') + ' annotate')
     ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
     <BLANKLINE>
     Annotated sections
@@ -1268,7 +1269,7 @@
     ... op = base
     ... """)
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Installing debug.
     op buildout
@@ -1338,7 +1339,7 @@
     ... name = base
     ... """)
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling debug.
     Installing debug.
@@ -1400,7 +1401,7 @@
     ... """ % dict(url=server_url))
 
 
-    >>> print system(buildout+ ' -c client.cfg'),
+    >>> run(buildout+ ' -c client.cfg')
     Develop: '/sample-buildout/recipes'
     Uninstalling debug.
     Installing debug.
@@ -1431,7 +1432,7 @@
     ... name = remote
     ... """)
 
-    >>> print system(buildout + ' -c ' + server_url + '/remote.cfg'),
+    >>> run(buildout + ' -c ' + server_url + '/remote.cfg')
     While:
       Initializing.
     Error: Missing option: buildout:directory
@@ -1441,10 +1442,9 @@
 files loaded from URLs.  In this case, the buildout directory would
 normally be defined on the command line:
 
-    >>> print system(buildout
-    ...              + ' -c ' + server_url + '/remote.cfg'
+    >>> run(buildout + ' -c ' + server_url + '/remote.cfg'
     ...              + ' buildout:directory=' + sample_buildout
-    ...              ),
+    ...              )
     Develop: '/sample-buildout/recipes'
     Uninstalling debug.
     Installing debug.
@@ -1473,7 +1473,7 @@
     ... """)
 
     >>> os.environ['HOME'] = home
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling debug.
     Installing debug.
@@ -1490,7 +1490,7 @@
 A buildout command-line argument, -U, can be used to suppress reading
 user defaults:
 
-    >>> print system(buildout + ' -U'),
+    >>> run(buildout + ' -U')
     Develop: '/sample-buildout/recipes'
     Uninstalling debug.
     Installing debug.
@@ -1519,7 +1519,7 @@
     ... extends = b1.cfg b2.cfg
     ... """)
 
-    >>> print system(buildout),
+    >>> run(buildout)
     name base
     op1 b1 1
     op2 b2 2
@@ -1562,7 +1562,7 @@
     ...         self.options = options
     ...
     ...     def install(self):
-    ...         print "chkconfig --add %s" % self.options['script']
+    ...         print("chkconfig --add %s" % self.options['script'])
     ...         return ()
     ...
     ...     def update(self):
@@ -1570,7 +1570,7 @@
     ...
     ...
     ... def uninstall_service(name, options):
-    ...     print "chkconfig --del %s" % options['script']
+    ...     print("chkconfig --del %s" % options['script'])
     ... """)
 
 To use these recipes we must register them using entry points. Make
@@ -1609,20 +1609,18 @@
 
 When the buildout is run the service will be installed
 
-    >>> print system(buildout)
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling debug.
     Installing service.
     chkconfig --add /path/to/script
-    <BLANKLINE>
 
 The service has been installed. If the buildout is run again with no
 changes, the service shouldn't be changed.
 
-    >>> print system(buildout)
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Updating service.
-    <BLANKLINE>
 
 Now we change the service part to trigger uninstallation and
 re-installation.
@@ -1638,14 +1636,13 @@
     ... script = /path/to/a/different/script
     ... """)
 
-    >>> print system(buildout)
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling service.
     Running uninstall recipe.
     chkconfig --del /path/to/script
     Installing service.
     chkconfig --add /path/to/a/different/script
-    <BLANKLINE>
 
 Now we remove the service part, and add another part.
 
@@ -1659,14 +1656,13 @@
     ... recipe = recipes:debug
     ... """)
 
-    >>> print system(buildout)
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling service.
     Running uninstall recipe.
     chkconfig --del /path/to/a/different/script
     Installing debug.
     recipe recipes:debug
-    <BLANKLINE>
 
 Uninstall recipes don't have to take care of removing all the files
 and directories created by the part. This is still done automatically,
@@ -1684,7 +1680,7 @@
     ... def backup_directory(name, options):
     ...     path = options['path']
     ...     size = len(os.listdir(path))
-    ...     print "backing up directory %s of size %s" % (path, size)
+    ...     print("backing up directory %s of size %s" % (path, size))
     ... """)
 
 It must be registered with the zc.buildout.uninstall entry
@@ -1726,14 +1722,13 @@
 
 Run the buildout to install the part.
 
-    >>> print system(buildout)
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling debug.
     Installing dir.
     dir: Creating directory my_directory
     Installing debug.
     recipe recipes:debug
-    <BLANKLINE>
 
 Now we remove the part from the configuration file.
 
@@ -1750,14 +1745,13 @@
 When the buildout is run the part is removed, and the uninstall recipe
 is run before the directory is deleted.
 
-    >>> print system(buildout)
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling dir.
     Running uninstall recipe.
     backing up directory /sample-buildout/my_directory of size 0
     Updating debug.
     recipe recipes:debug
-    <BLANKLINE>
 
 Now we will return the registration to normal for the benefit of the
 rest of the examples.
@@ -1855,7 +1849,7 @@
 Note that we used the installed buildout option to specify an
 alternate file to store information about installed parts.
 
-    >>> print system(buildout+' -c other.cfg debug:op1=foo -v'),
+    >>> run(buildout+' -c other.cfg debug:op1=foo -v')
     Develop: '/sample-buildout/recipes'
     Installing debug.
     name other
@@ -1868,7 +1862,7 @@
 
 Options can also be combined in the usual Unix way, as in:
 
-    >>> print system(buildout+' -vcother.cfg debug:op1=foo'),
+    >>> run(buildout+' -vcother.cfg debug:op1=foo')
     Develop: '/sample-buildout/recipes'
     Updating debug.
     name other
@@ -1909,7 +1903,7 @@
     ... recipe = recipes:debug
     ... """)
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling debug.
     Installing debug.
@@ -1993,7 +1987,7 @@
 
 and run the buildout specifying just d3 and d4:
 
-    >>> print system(buildout+' install d3 d4'),
+    >>> run(buildout+' install d3 d4')
     Develop: '/sample-buildout/recipes'
     Uninstalling d3.
     Installing d3.
@@ -2064,7 +2058,7 @@
 
 Now, if we run the buildout without the install command:
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling d2.
     Uninstalling d1.
@@ -2121,7 +2115,7 @@
     ...    work = os.path.join(alt, 'work'),
     ... ))
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Creating directory '/sample-alt/scripts'.
     Creating directory '/sample-alt/work'.
     Creating directory '/sample-alt/basket'.
@@ -2157,7 +2151,7 @@
     ...    recipes=os.path.join(sample_buildout, 'recipes'),
     ...    ))
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Creating directory '/sample-alt/bin'.
     Creating directory '/sample-alt/parts'.
     Creating directory '/sample-alt/eggs'.
@@ -2209,7 +2203,7 @@
 configuration file.  Because the verbosity is subtracted from the log
 level, we get a final log level of 20, which is the INFO level.
 
-    >>> print system(buildout),
+    >>> run(buildout)
     INFO Develop: '/sample-buildout/recipes'
 
 Predefined buildout options
@@ -2227,7 +2221,7 @@
     ... parts =
     ... """)
 
-    >>> print system(buildout+' -vv'), # doctest: +NORMALIZE_WHITESPACE
+    >>> run(buildout+' -vv') # doctest: +NORMALIZE_WHITESPACE
     Installing 'zc.buildout', 'setuptools'.
     We have a develop egg: zc.buildout X.X.
     We have the best distribution that satisfies 'setuptools'.
@@ -2410,9 +2404,8 @@
 
     >>> sample_bootstrapped = tmpdir('sample-bootstrapped')
 
-    >>> print system(buildout
-    ...              +' -c'+os.path.join(sample_bootstrapped, 'setup.cfg')
-    ...              +' init'),
+    >>> run(buildout +' -c'+os.path.join(sample_bootstrapped, 'setup.cfg')
+    ...              +' init')
     Creating '/sample-bootstrapped/setup.cfg'.
     Creating directory '/sample-bootstrapped/bin'.
     Creating directory '/sample-bootstrapped/parts'.
@@ -2451,16 +2444,15 @@
     ... parts =
     ... ''')
 
-    >>> print system(buildout
-    ...              +' -c'+os.path.join(sample_bootstrapped, 'setup.cfg')
-    ...              +' bootstrap'),
+    >>> run(buildout +' -c'+os.path.join(sample_bootstrapped, 'setup.cfg')
+    ...              +' bootstrap')
     Generated script '/sample-bootstrapped/bin/buildout'.
 
     >>> buildout_script = join(sample_bootstrapped, 'bin', 'buildout')
     >>> import sys
     >>> if sys.platform.startswith('win'):
     ...     buildout_script += '-script.py'
-    >>> print open(buildout_script).read() # doctest: +ELLIPSIS
+    >>> print(open(buildout_script).read()) # doctest: +ELLIPSIS
     #!... -S
     <BLANKLINE>
     import os
@@ -2500,9 +2492,8 @@
 
     >>> sample_bootstrapped2 = tmpdir('sample-bootstrapped2')
 
-    >>> print system(buildout
-    ...              +' -c'+os.path.join(sample_bootstrapped2, 'setup.cfg')
-    ...              +' bootstrap'),
+    >>> run(buildout +' -c'+os.path.join(sample_bootstrapped2, 'setup.cfg')
+    ...              +' bootstrap')
     While:
       Initializing.
     Error: Couldn't open /sample-bootstrapped2/setup.cfg
@@ -2513,9 +2504,8 @@
     ... parts =
     ... """)
 
-    >>> print system(buildout
-    ...              +' -c'+os.path.join(sample_bootstrapped2, 'setup.cfg')
-    ...              +' bootstrap'),
+    >>> run(buildout +' -c'+os.path.join(sample_bootstrapped2, 'setup.cfg')
+    ...              +' bootstrap')
     Creating directory '/sample-bootstrapped2/bin'.
     Creating directory '/sample-bootstrapped2/parts'.
     Creating directory '/sample-bootstrapped2/eggs'.
@@ -2653,7 +2643,7 @@
     ... recipe = recipes:debug
     ... """)
 
-    >>> print system(buildout+' buildout:installed=inst.cfg'),
+    >>> run(buildout+' buildout:installed=inst.cfg')
     Develop: '/sample-buildout/recipes'
     Installing debug.
     recipe recipes:debug
@@ -2675,7 +2665,7 @@
 buildout installed option:
 
     >>> os.remove('inst.cfg')
-    >>> print system(buildout+' buildout:installed='),
+    >>> run(buildout+' buildout:installed=')
     Develop: '/sample-buildout/recipes'
     Installing debug.
     recipe recipes:debug
@@ -2701,7 +2691,7 @@
     ... parts =
     ... """)
 
-    >>> print system(buildout+' buildout:installed=inst.cfg'),
+    >>> run(buildout+' buildout:installed=inst.cfg')
 
     >>> ls(sample_buildout)
     -  b1.cfg
@@ -2738,9 +2728,9 @@
     >>> write(sample_bootstrapped, 'demo', 'demo.py',
     ... """
     ... def ext(buildout):
-    ...     print 'ext', list(buildout)
+    ...     print('ext', list(buildout))
     ... def unload(buildout):
-    ...     print 'unload', list(buildout)
+    ...     print('unload', list(buildout))
     ... """)
 
     >>> write(sample_bootstrapped, 'demo', 'setup.py',
@@ -2770,7 +2760,7 @@
     ... """)
 
     >>> os.chdir(sample_bootstrapped)
-    >>> print system(os.path.join(sample_bootstrapped, 'bin', 'buildout')),
+    >>> run(os.path.join(sample_bootstrapped, 'bin', 'buildout'))
     Develop: '/sample-bootstrapped/demo'
 
 Now we can add the extensions option.  We were a bit tricky and ran
@@ -2790,7 +2780,7 @@
 
 We see that our extension is loaded and executed:
 
-    >>> print system(os.path.join(sample_bootstrapped, 'bin', 'buildout')),
+    >>> run(os.path.join(sample_bootstrapped, 'bin', 'buildout'))
     ext ['buildout']
     Develop: '/sample-bootstrapped/demo'
     unload ['buildout']

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/debugging.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/debugging.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/debugging.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -56,7 +56,7 @@
 
 If we run the buildout, we'll get an error:
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Installing data-dir.
     While:
@@ -67,11 +67,11 @@
 If we want to debug the error, we can add the -D option. Here's we'll
 supply some input:
 
-    >>> print system(buildout+" -D", """\
+    >>> run(buildout+" -D", """\
     ... up
     ... p self.options.keys()
     ... q
-    ... """),
+    ... """)
     Develop: '/sample-buildout/recipes'
     Installing data-dir.
     > /zc/buildout/buildout.py(925)__getitem__()

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/dependencylinks.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/dependencylinks.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/dependencylinks.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -54,14 +54,13 @@
 
 Now we can run the buildout.
 
-    >>> print system(buildout)
+    >>> run(buildout)
     GET 200 /
     GET 200 /demoneeded-1.2c1.zip
     Develop: '/sample-buildout/depdemo'
     Installing eggs.
     Getting distribution for 'demoneeded'.
     Got demoneeded 1.2c1.
-    <BLANKLINE>
 
 Notice that the egg was retrieved from the logging server.
 
@@ -83,7 +82,7 @@
     ...     for egg in glob(join(sample_buildout, 'eggs', 'demoneeded*.egg')):
     ...         remove(sample_buildout, 'eggs', egg)
     >>> remove_demoneeded_egg()
-    >>> print system(buildout) # doctest: +ELLIPSIS
+    >>> run(buildout) # doctest: +ELLIPSIS
     Develop: '/sample-buildout/depdemo'
     ...
     Getting distribution for 'demoneeded'.
@@ -91,7 +90,6 @@
       Updating eggs.
       Getting distribution for 'demoneeded'.
     Error: Couldn't find a distribution for 'demoneeded'.
-    <BLANKLINE>
 
 Now it can't find the dependency since neither the buildout
 configuration nor setup specifies where to look.
@@ -111,12 +109,11 @@
     ... eggs = depdemo
     ... ''' % link_server)
 
-    >>> print system(buildout)
+    >>> run(buildout)
     Develop: '/sample-buildout/depdemo'
     Installing eggs.
     Getting distribution for 'demoneeded'.
     Got demoneeded 1.2c1.
-    <BLANKLINE>
 
 This time the dependency egg was found on the server without logging
 configured.
@@ -133,13 +130,12 @@
     ... '''  % link_server2)
 
     >>> remove_demoneeded_egg()
-    >>> print system(buildout) #doctest: +ELLIPSIS
+    >>> run(buildout) #doctest: +ELLIPSIS
     GET 200 /...
     Develop: '/sample-buildout/depdemo'
     Updating eggs.
     Getting distribution for 'demoneeded'.
     Got demoneeded 1.2c1.
-    <BLANKLINE>
 
 So when both setuptools and buildout specify places to search for
 eggs, the dependency_links takes precedence over find-links.
@@ -165,12 +161,11 @@
     ... ''' % link_server)
 
     >>> remove_demoneeded_egg()
-    >>> print system(buildout)
+    >>> run(buildout)
     Develop: '/sample-buildout/depdemo'
     Updating eggs.
     Getting distribution for 'demoneeded'.
     Got demoneeded 1.2c1.
-    <BLANKLINE>
 
 Notice that this time the egg isn't downloaded from the logging server.
 
@@ -190,10 +185,9 @@
     ... eggs = depdemo
     ... ''' % link_server)
     >>> remove_demoneeded_egg()
-    >>> print system(buildout) #doctest: +ELLIPSIS
+    >>> run(buildout) #doctest: +ELLIPSIS
     GET 200 /...
     Develop: '/sample-buildout/depdemo'
     Updating eggs.
     Getting distribution for 'demoneeded'.
     Got demoneeded 1.2c1.
-    <BLANKLINE>

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/download.py
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/download.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/download.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -23,14 +23,15 @@
 import os.path
 import re
 import shutil
+import sys
 import tempfile
-import urllib
-import urlparse
+import urllib.request, urllib.parse, urllib.error
+import urllib.parse
 import zc.buildout
 
 
-class URLOpener(urllib.FancyURLopener):
-    http_error_default = urllib.URLopener.http_error_default
+class URLOpener(urllib.request.FancyURLopener):
+    http_error_default = urllib.request.URLopener.http_error_default
 
 
 class ChecksumError(zc.buildout.UserError):
@@ -157,7 +158,7 @@
         if re.match(r"^[A-Za-z]:\\", url):
             url = 'file:' + url
 
-        parsed_url = urlparse.urlparse(url, 'file')
+        parsed_url = urllib.parse.urlparse(url, 'file')
         url_scheme, _, url_path = parsed_url[:3]
         if url_scheme == 'file':
             self.logger.debug('Using local resource %s' % url)
@@ -172,18 +173,19 @@
                 "Couldn't download %r in offline mode." % url)
 
         self.logger.info('Downloading %s' % url)
-        urllib._urlopener = url_opener
+        urllib.request._urlopener = url_opener
         handle, tmp_path = tempfile.mkstemp(prefix='buildout-')
         try:
-            tmp_path, headers = urllib.urlretrieve(url, tmp_path)
+            tmp_path, headers = urllib.request.urlretrieve(url, tmp_path)
             if not check_md5sum(tmp_path, md5sum):
                 raise ChecksumError(
                     'MD5 checksum mismatch downloading %r' % url)
-        except IOError, e:
+        except IOError:
+            e = sys.exc_info()[1]
             os.remove(tmp_path)
             raise zc.buildout.UserError("Error downloading extends for URL "
-                              "%s: %r" % (url, e[1:3]))
-        except Exception, e:
+                              "%s:\n%s" % (url, e))
+        except Exception:
             os.remove(tmp_path)
             raise
         finally:
@@ -200,11 +202,11 @@
 
         """
         if self.hash_name:
-            return md5(url).hexdigest()
+            return md5(url.encode('utf8')).hexdigest()
         else:
             if re.match(r"^[A-Za-z]:\\", url):
                 url = 'file:' + url
-            parsed = urlparse.urlparse(url, 'file')
+            parsed = urllib.parse.urlparse(url, 'file')
             url_path = parsed[2]
 
             if parsed[0] == 'file':

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/download.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/download.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/download.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -28,7 +28,7 @@
 
 >>> from zc.buildout.download import Download
 >>> download = Download()
->>> print download.cache_dir
+>>> print(download.cache_dir)
 None
 
 Downloading a file is achieved by calling the utility with the URL as an
@@ -37,7 +37,7 @@
 meant to be cleaned up during the same buildout run:
 
 >>> path, is_temp = download(server_url+'foo.txt')
->>> print path
+>>> print(path)
 /.../buildout-...
 >>> cat(path)
 This is a foo text.
@@ -59,8 +59,8 @@
 When trying to access a file that doesn't exist, we'll get an exception:
 
 >>> try: download(server_url+'not-there') # doctest: +ELLIPSIS
-... except: print 'download error'
-... else: print 'woops'
+... except: print('download error')
+... else: print('woops')
 download error
 
 Downloading a local file doesn't produce a temporary file but simply returns
@@ -75,34 +75,32 @@
 ... except ImportError: from md5 import new as md5
 
 >>> path, is_temp = download(server_url+'foo.txt',
-...                          md5('This is a foo text.').hexdigest())
+...                   md5('This is a foo text.'.encode()).hexdigest())
 >>> is_temp
 True
 >>> remove(path)
 
->>> download(server_url+'foo.txt',
-...          md5('The wrong text.').hexdigest())
-Traceback (most recent call last):
-ChecksumError: MD5 checksum mismatch downloading 'http://localhost/foo.txt'
+>>> print(raises('ChecksumError', download, server_url+'foo.txt',
+...                 md5('The wrong text.'.encode()).hexdigest()))
+MD5 checksum mismatch downloading 'http://localhost/foo.txt'
 
 The error message in the event of an MD5 checksum mismatch for a local file
 reads somewhat differently:
 
 >>> download(join(server_data, 'foo.txt'),
-...               md5('This is a foo text.').hexdigest())
+...               md5('This is a foo text.'.encode()).hexdigest())
 ('/sample_files/foo.txt', False)
 
->>> download(join(server_data, 'foo.txt'),
-...          md5('The wrong text.').hexdigest())
-Traceback (most recent call last):
-ChecksumError: MD5 checksum mismatch for local resource at '/sample_files/foo.txt'.
+>>> print(raises('ChecksumError', download, join(server_data, 'foo.txt'),
+...          md5('The wrong text.'.encode()).hexdigest()))
+MD5 checksum mismatch for local resource at '/sample_files/foo.txt'.
 
 Finally, we can download the file to a specified place in the file system:
 
 >>> target_dir = tmpdir('download-target')
 >>> path, is_temp = download(server_url+'foo.txt',
 ...                          path=join(target_dir, 'downloaded.txt'))
->>> print path
+>>> print(path)
 /download-target/downloaded.txt
 >>> cat(path)
 This is a foo text.
@@ -112,9 +110,8 @@
 Trying to download a file in offline mode will result in an error:
 
 >>> download = Download(cache=None, offline=True)
->>> download(server_url+'foo.txt')
-Traceback (most recent call last):
-UserError: Couldn't download 'http://localhost/foo.txt' in offline mode.
+>>> print(raises('UserError', download, server_url+'foo.txt'))
+Couldn't download 'http://localhost/foo.txt' in offline mode.
 
 As an exception to this rule, file system paths and URLs in the ``file``
 scheme will still work:
@@ -136,7 +133,7 @@
 
 >>> cache = tmpdir('download-cache')
 >>> download = Download(cache=cache)
->>> print download.cache_dir
+>>> print(download.cache_dir)
 /download-cache/
 
 Simple usage
@@ -148,7 +145,7 @@
 
 >>> ls(cache)
 >>> path, is_temp = download(server_url+'foo.txt')
->>> print path
+>>> print(path)
 /download-cache/foo.txt
 >>> cat(path)
 This is a foo text.
@@ -160,7 +157,7 @@
 
 >>> write(server_data, 'foo.txt', 'The wrong text.')
 >>> path, is_temp = download(server_url+'foo.txt')
->>> print path
+>>> print(path)
 /download-cache/foo.txt
 >>> cat(path)
 This is a foo text.
@@ -168,10 +165,11 @@
 If we specify an MD5 checksum for a file that is already in the cache, the
 cached copy's checksum will be verified:
 
->>> download(server_url+'foo.txt', md5('The wrong text.').hexdigest())
-Traceback (most recent call last):
-ChecksumError: MD5 checksum mismatch for cached download
-               from 'http://localhost/foo.txt' at '/download-cache/foo.txt'
+>>> print(raises('ChecksumError', download, server_url+'foo.txt',
+...       md5('The wrong text.'.encode()).hexdigest()))
+... # doctest: +NORMALIZE_WHITESPACE
+MD5 checksum mismatch for cached download
+from 'http://localhost/foo.txt' at '/download-cache/foo.txt'
 
 Trying to access another file at a different URL which has the same base name
 will result in the cached copy being used:
@@ -179,7 +177,7 @@
 >>> mkdir(server_data, 'other')
 >>> write(server_data, 'other', 'foo.txt', 'The wrong text.')
 >>> path, is_temp = download(server_url+'other/foo.txt')
->>> print path
+>>> print(path)
 /download-cache/foo.txt
 >>> cat(path)
 This is a foo text.
@@ -194,7 +192,7 @@
 
 >>> path, is_temp = download(server_url+'foo.txt',
 ...                          path=join(target_dir, 'downloaded.txt'))
->>> print path
+>>> print(path)
 /download-target/downloaded.txt
 >>> cat(path)
 This is a foo text.
@@ -208,7 +206,7 @@
 
 >>> path, is_temp = download(server_url+'foo.txt',
 ...                          path=join(target_dir, 'downloaded.txt'))
->>> print path
+>>> print(path)
 /download-target/downloaded.txt
 >>> cat(path)
 This is a foo text.
@@ -247,26 +245,28 @@
 
 However, resources with checksum mismatches will not be copied to the cache:
 
->>> download(server_url+'foo.txt', md5('The wrong text.').hexdigest())
-Traceback (most recent call last):
-ChecksumError: MD5 checksum mismatch downloading 'http://localhost/foo.txt'
+>>> print(raises('ChecksumError', download, server_url+'foo.txt',
+... md5('The wrong text.'.encode()).hexdigest()))
+MD5 checksum mismatch downloading 'http://localhost/foo.txt'
+
 >>> ls(cache)
 
 >>> remove(path)
 
 If the file is completely missing it should notify the user of the error:
 
->>> download(server_url+'bar.txt')
-Traceback (most recent call last):
-UserError: Error downloading extends for URL http://localhost/bar.txt: (404, 'Not Found')
+>>> print(raises('UserError', download, server_url+'bar.txt'))
+Error downloading extends for URL http://localhost/bar.txt:
+HTTP Error 404: Not Found
+
 >>> ls(cache)
 
 Finally, let's see what happens if the download cache to be used doesn't exist
 as a directory in the file system yet:
 
->>> Download(cache=join(cache, 'non-existent'))(server_url+'foo.txt')
-Traceback (most recent call last):
-UserError: The directory:
+>>> print(raises('UserError',
+...    Download(cache=join(cache, 'non-existent')), server_url+'foo.txt'))
+The directory:
 '/download-cache/non-existent'
 to be used as a download cache doesn't exist.
 
@@ -281,7 +281,7 @@
 download cache. Let's use a namespace "test" instead:
 
 >>> download = Download(cache=cache, namespace='test')
->>> print download.cache_dir
+>>> print(download.cache_dir)
 /download-cache/test
 
 The namespace sub-directory hasn't been created yet:
@@ -292,7 +292,7 @@
 of the file inside it:
 
 >>> path, is_temp = download(server_url+'foo.txt')
->>> print path
+>>> print(path)
 /download-cache/test/foo.txt
 >>> ls(cache)
 d test
@@ -311,7 +311,7 @@
 >>> write(cache, 'foo.txt', 'The wrong text.')
 
 >>> path, is_temp = download(server_url+'foo.txt')
->>> print path
+>>> print(path)
 /download-cache/test/foo.txt
 >>> cat(path)
 This is a foo text.
@@ -332,7 +332,7 @@
 
 >>> download = Download(cache=cache, hash_name=True)
 >>> path, is_temp = download(server_url+'foo.txt')
->>> print path
+>>> print(path)
 /download-cache/09f5793fcdc1716727f72d49519c688d
 >>> cat(path)
 This is a foo text.
@@ -344,7 +344,8 @@
 the test is run, so we don't actually know the full URL of the file. Let's
 check that the checksum actually belongs to the particular URL used:
 
->>> path.lower() == join(cache, md5(server_url+'foo.txt').hexdigest()).lower()
+>>> path.lower() == join(
+...    cache, md5((server_url+'foo.txt').encode('utf8')).hexdigest()).lower()
 True
 
 The cached copy is used when downloading the file again:
@@ -362,11 +363,13 @@
 cache under a different name:
 
 >>> path2, is_temp = download(server_url+'other/foo.txt')
->>> print path2
+>>> print(path2)
 /download-cache/537b6d73267f8f4447586989af8c470e
 >>> path == path2
 False
->>> path2.lower() == join(cache, md5(server_url+'other/foo.txt').hexdigest()).lower()
+>>> path2.lower() == join(
+...   cache,
+...   md5((server_url+'other/foo.txt').encode('utf8')).hexdigest()).lower()
 True
 >>> cat(path)
 This is a foo text.
@@ -390,7 +393,7 @@
 cache is configured in the first place:
 
 >>> download = Download(cache=cache, fallback=True)
->>> print download.cache_dir
+>>> print(download.cache_dir)
 /download-cache/
 
 A downloaded file will be cached:
@@ -408,8 +411,8 @@
 
 >>> remove(server_data, 'foo.txt')
 >>> try: Download()(server_url+'foo.txt') # doctest: +ELLIPSIS
-... except: print 'download error'
-... else: print 'woops'
+... except: print('download error')
+... else: print('woops')
 download error
 >>> path, is_temp = download(server_url+'foo.txt')
 >>> cat(path)
@@ -426,7 +429,7 @@
 
 >>> offline_download = Download(cache=cache, offline=True, fallback=True)
 >>> path, is_temp = offline_download(server_url+'foo.txt')
->>> print path
+>>> print(path)
 /download-cache/foo.txt
 >>> cat(path)
 This is a foo text.
@@ -446,9 +449,10 @@
 copy will neither be used nor overwritten:
 
 >>> write(server_data, 'foo.txt', 'This is a foo text.')
->>> download(server_url+'foo.txt', md5('The wrong text.').hexdigest())
-Traceback (most recent call last):
-ChecksumError: MD5 checksum mismatch downloading 'http://localhost/foo.txt'
+>>> print(raises('ChecksumError', download, server_url+'foo.txt',
+...          md5('The wrong text.'.encode()).hexdigest()))
+MD5 checksum mismatch downloading 'http://localhost/foo.txt'
+
 >>> cat(cache, 'foo.txt')
 The wrong text.
 
@@ -466,7 +470,7 @@
 option:
 
 >>> download = Download({'download-cache': cache}, namespace='cmmi')
->>> print download.cache_dir
+>>> print(download.cache_dir)
 /download-cache/cmmi
 
 If the ``download-cache`` option specifies a relative path, it is understood
@@ -474,18 +478,18 @@
 that is given:
 
 >>> download = Download({'download-cache': 'relative-cache'})
->>> print download.cache_dir
+>>> print(download.cache_dir)
 /sample-buildout/relative-cache/
 
 >>> download = Download({'directory': join(sample_buildout, 'root'),
 ...                      'download-cache': 'relative-cache'})
->>> print download.cache_dir
+>>> print(download.cache_dir)
 /sample-buildout/root/relative-cache/
 
 Keyword parameters take precedence over the corresponding options:
 
 >>> download = Download({'download-cache': cache}, cache=None)
->>> print download.cache_dir
+>>> print(download.cache_dir)
 None
 
 Whether to assume offline mode can be inferred from either the ``offline`` or
@@ -537,9 +541,9 @@
 requires text files to be treated as binary to avoid implicit line-ending
 conversions:
 
->>> text = 'First line of text.\r\nSecond line.\r\n'
+>>> text = 'First line of text.\r\nSecond line.\r\n'.encode()
 >>> f = open(join(server_data, 'foo.txt'), 'wb')
->>> f.write(text)
+>>> _ = f.write(text)
 >>> f.close()
 >>> path, is_temp = Download()(server_url+'foo.txt', md5(text).hexdigest())
 >>> remove(path)

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/downloadcache.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/downloadcache.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/downloadcache.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -31,7 +31,7 @@
 We specified a link server that has some distributions available for
 download:
 
-    >>> print get(link_server),
+    >>> print_(get(link_server))
     <html><body>
     <a href="bigdemo-0.1-py2.4.egg">bigdemo-0.1-py2.4.egg</a><br>
     <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br>
@@ -45,8 +45,8 @@
     <a href="index/">index/</a><br>
     <a href="other-1.0-py2.4.egg">other-1.0-py2.4.egg</a><br>
     </body></html>
-    
 
+
 We'll enable logging on the link server so we can see what's going on:
 
     >>> get(link_server+'enable_server_logging')
@@ -58,7 +58,7 @@
 If we run the buildout, we'll see the eggs installed from the link
 server as usual:
 
-    >>> print system(buildout),
+    >>> run(buildout)
     GET 200 /
     GET 200 /demo-0.2-py2.4.egg
     GET 200 /demoneeded-1.2c1.zip
@@ -87,8 +87,8 @@
     >>> for  f in os.listdir('eggs'):
     ...     if f.startswith('demo'):
     ...         remove('eggs', f)
-   
-    >>> print system(buildout),
+
+    >>> run(buildout)
     GET 200 /
     Updating eggs.
     Getting distribution for 'demo==0.2'.
@@ -131,7 +131,7 @@
     ... eggs = demo
     ... ''' % globals())
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Uninstalling eggs.
     Installing eggs.
     Getting distribution for 'demo'.

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/easy_install.py
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/easy_install.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/easy_install.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -26,6 +26,7 @@
 import pkg_resources
 import py_compile
 import re
+import setuptools
 import setuptools.archive_util
 import setuptools.command.setopt
 import setuptools.package_index
@@ -52,6 +53,7 @@
 
 is_win32 = sys.platform == 'win32'
 is_jython = sys.platform.startswith('java')
+setuptools_key = pkg_resources.Requirement.parse('setuptools').key
 is_distribute = (
     pkg_resources.Requirement.parse('setuptools').key=='distribute')
 
@@ -72,7 +74,7 @@
     jython_os_name = (java.lang.System.getProperties()['os.name']).lower()
 
 setuptools_loc = pkg_resources.working_set.find(
-    pkg_resources.Requirement.parse('setuptools')
+    pkg_resources.Requirement.parse(setuptools_key)
     ).location
 
 # Include buildout and setuptools eggs in paths.  We prevent dupes just to
@@ -94,11 +96,11 @@
     stdout, stderr = subprocess.Popen(
         [executable, '-S', '-c',
          'try:\n'
-         '    import ConfigParser\n'
+         '    import pickle\n'
          'except ImportError:\n'
-         '    print 1\n'
+         '    print(1)\n'
          'else:\n'
-         '    print 0\n'],
+         '    print(0)\n'],
         stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
     return bool(int(stdout.strip()))
 
@@ -129,7 +131,7 @@
         cmd.extend(args)
         cmd.extend([
             "-c", "import sys, os;"
-            "print repr([os.path.normpath(p) for p in sys.path if p])"])
+            "print(repr([os.path.normpath(p) for p in sys.path if p]))"])
         # Windows needs some (as yet to be determined) part of the real env.
         env = os.environ.copy()
         # We need to make sure that PYTHONPATH, which will often be set
@@ -184,10 +186,10 @@
                              close_fds=not is_win32)
         i, o = (p.stdin, p.stdout)
         i.close()
-        version = o.read().strip()
+        version = o.read().strip().decode()
         o.close()
         pystring, version = version.split()
-        assert pystring == 'Python'
+        assert pystring == 'Python', pystring
         version = re.match('(\d[.]\d)([.].*\d)?$', version).group(1)
         _versions[executable] = version
         return version
@@ -716,6 +718,13 @@
 
     def _get_dist(self, requirement, ws, always_unzip):
 
+        if (requirement.project_name == 'setuptools' and
+            (ws.find(pkg_resources.Requirement.parse('distribute'))
+             or sys.version_info[0] >= 3
+             )
+            ):
+            requirement = pkg_resources.Requirement.parse('distribute')
+
         __doing__ = 'Getting distribution for %r.', str(requirement)
 
         # Maybe an existing dist is already the best dist that satisfies the
@@ -849,7 +858,7 @@
                         "does not require setuptools.",
                         dist)
                 requirement = self._constrain(
-                    pkg_resources.Requirement.parse('setuptools')
+                    pkg_resources.Requirement.parse(setuptools_key)
                     )
                 if ws.find(requirement) is None:
                     for dist in self._get_dist(requirement, ws, False):
@@ -857,8 +866,6 @@
 
 
     def _constrain(self, requirement):
-        if is_distribute and requirement.key == 'setuptools':
-            requirement = pkg_resources.Requirement.parse('distribute')
         version = self._versions.get(requirement.project_name)
         if version:
             if version not in requirement:
@@ -914,9 +921,21 @@
         while requirements:
             # Process dependencies breadth-first.
             req = self._constrain(requirements.pop(0))
+
             if req in processed:
                 # Ignore cyclic or redundant dependencies.
                 continue
+
+            if (req.project_name == 'setuptools' and
+                (ws.find(pkg_resources.Requirement.parse('distribute'))
+                 or sys.version_info[0] >= 3
+                 )
+                ):
+                processed[req] = True
+                req = pkg_resources.Requirement.parse('distribute')
+                if req in processed:
+                    continue
+
             dist = best.get(req.key)
             if dist is None:
                 # Find the best distribution and add it to the map.
@@ -924,7 +943,7 @@
                 if dist is None:
                     try:
                         dist = best[req.key] = env.best_match(req, ws)
-                    except pkg_resources.VersionConflict, err:
+                    except pkg_resources.VersionConflict as err:
                         raise VersionConflict(err, ws)
                     if dist is None or (
                         dist.location in self._site_packages and not
@@ -1157,12 +1176,12 @@
         undo.append(lambda: os.remove(tsetup))
         undo.append(lambda: os.close(fd))
 
-        os.write(fd, runsetup_template % dict(
+        os.write(fd, (runsetup_template % dict(
             setuptools=setuptools_loc,
             setupdir=directory,
             setup=setup,
             __file__ = setup,
-            ))
+            )).encode())
 
         tmp3 = tempfile.mkdtemp('build', dir=dest)
         undo.append(lambda : shutil.rmtree(tmp3))
@@ -1305,7 +1324,7 @@
     for p in path:
         if p not in unique_path:
             unique_path.append(p)
-    return map(realpath, unique_path)
+    return list(map(realpath, unique_path))
 
 def _generate_scripts(reqs, working_set, dest, path, scripts, relative_paths,
                       initialization, executable, arguments,
@@ -1463,7 +1482,7 @@
     if changed:
         open(script_name, 'w').write(contents)
         try:
-            os.chmod(script_name, 0755)
+            os.chmod(script_name, 0o755)
         except (AttributeError, os.error):
             pass
         logger.info("Generated %s %r.", logged_type, full_name)
@@ -1548,7 +1567,7 @@
         if _opt == '-i':
             _interactive = True
         elif _opt == '-c':
-            exec _val
+            exec(_val)
         elif _opt == '-m':
             sys.argv[1:] = _args
             _args = []
@@ -1559,7 +1578,7 @@
         sys.argv[:] = _args
         __file__ = _args[0]
         del _options, _args
-        execfile(__file__)
+        exec(compile(open(__file__).read(), __file__, "exec"))
 
 if _interactive:
     del _interactive
@@ -1578,7 +1597,7 @@
            "import imp; "
            "fp, path, desc = imp.find_module(%r); "
            "fp.close(); "
-           "print path" % (name,)]
+           "print(path)" % (name,)]
     env = os.environ.copy()
     # We need to make sure that PYTHONPATH, which will often be set to
     # include a custom buildout-generated site.py, is not set, or else
@@ -1595,7 +1614,7 @@
         return None
     # else: ...
     res = stdout.strip()
-    if res.endswith('.pyc') or res.endswith('.pyo'):
+    if res.endswith('.pyc'.encode()) or res.endswith('.pyo'.encode()):
         raise RuntimeError('Cannot find uncompiled version of %s' % (name,))
     if not os.path.exists(res):
         raise RuntimeError(
@@ -1816,7 +1835,8 @@
 
 os.chdir(%(setupdir)r)
 sys.argv[0] = %(setup)r
-execfile(%(setup)r)
+
+exec(compile(open(%(setup)r).read(), %(setup)r, "exec"))
 """
 
 

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/easy_install.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/easy_install.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/easy_install.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -107,7 +107,7 @@
 
 We have a link server that has a number of eggs:
 
-    >>> print get(link_server),
+    >>> print_(get(link_server))
     <html><body>
     <a href="bigdemo-0.1-py2.4.egg">bigdemo-0.1-py2.4.egg</a><br>
     <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br>
@@ -138,7 +138,7 @@
 The working set contains the distributions we retrieved.
 
     >>> for dist in ws:
-    ...     print dist
+    ...     print(dist)
     demo 0.2
     demoneeded 1.1
 
@@ -182,7 +182,7 @@
     >>> ws = zc.buildout.easy_install.install(
     ...     ['demo'], dest, links=[link_server], index=link_server+'index/')
     >>> for dist in ws:
-    ...     print dist
+    ...     print(dist)
     demo 0.4c1
     demoneeded 1.2c1
 
@@ -207,7 +207,7 @@
     ...     links=[link_server], index=link_server+'index/')
 
     >>> for dist in ws:
-    ...     print dist
+    ...     print(dist)
     demo 0.3
     other 1.0
     demoneeded 1.0
@@ -313,15 +313,13 @@
     >>> import logging
     >>> logging.getLogger('zc.buildout.easy_install').propagate = False
 
-    >>> ws = zc.buildout.easy_install.install(
+    >>> _ = raises('IncompatibleVersionError',
+    ...     zc.buildout.easy_install.install,
     ...     ['demo >0.2'], dest, links=[link_server],
     ...     index=link_server+'index/',
     ...     versions = dict(demo='0.2', demoneeded='1.0'))
-    Traceback (most recent call last):
-    ...
-    IncompatibleVersionError: Bad version 0.2
 
-    >>> print handler
+    >>> print(handler)
     zc.buildout.easy_install DEBUG
       Installing 'demo >0.2'.
     zc.buildout.easy_install ERROR
@@ -336,7 +334,7 @@
     ...     ['demo'], dest, links=[link_server], index=link_server+'index/',
     ...     )
 
-    >>> print handler
+    >>> print(handler)
     zc.buildout.easy_install DEBUG
       Installing 'demo'.
     zc.buildout.easy_install DEBUG
@@ -362,12 +360,10 @@
 
 (The old setting is returned.)
 
-    >>> ws = zc.buildout.easy_install.install(
+    >>> print(raises('UserError', zc.buildout.easy_install.install,
     ...     ['demo'], dest, links=[link_server], index=link_server+'index/',
-    ...     )
-    Traceback (most recent call last):
-    ...
-    UserError: Picked: demo = 0.3
+    ...     ))
+    Picked: demo = 0.3
 
     >>> zc.buildout.easy_install.allow_picked_versions(True)
     False
@@ -455,12 +451,11 @@
     >>> zc.buildout.easy_install.clear_index_cache()
     >>> rmdir(example_dest)
     >>> example_dest = tmpdir('site-packages-example-install')
-    >>> workingset = zc.buildout.easy_install.install(
+    >>> print(raises('MissingDistribution', zc.buildout.easy_install.install,
     ...     ['demoneeded'], example_dest, links=[], executable=py_path,
-    ...     index=None)
-    Traceback (most recent call last):
-        ...
-    MissingDistribution: Couldn't find a distribution for 'demoneeded'.
+    ...     index=None))
+    Couldn't find a distribution for 'demoneeded'.
+
     >>> zc.buildout.easy_install.clear_index_cache()
 
 Now we'll reset the default.
@@ -764,7 +759,7 @@
             if _opt == '-i':
                 _interactive = True
             elif _opt == '-c':
-                exec _val
+                exec(_val)
             elif _opt == '-m':
                 sys.argv[1:] = _args
                 _args = []
@@ -775,7 +770,7 @@
             sys.argv[:] = _args
             __file__ = _args[0]
             del _options, _args
-            execfile(__file__)
+            exec(compile(open(__file__).read(), __file__, "exec"))
     <BLANKLINE>
     if _interactive:
         del _interactive
@@ -785,20 +780,20 @@
 
     >>> write('ascript', '''
     ... "demo doc"
-    ... print sys.argv
-    ... print (__name__, __file__, __doc__)
+    ... print(sys.argv)
+    ... print((__name__, __file__, __doc__))
     ... ''')
-    >>> print system(join(bin, 'py')+' ascript a b c'),
+    >>> run(join(bin, 'py')+' ascript a b c')
     ['ascript', 'a', 'b', 'c']
     ('__main__', 'ascript', 'demo doc')
 
 For Python 2.5 and higher, you can also use the -m option to run a
 module:
 
-    >>> print system(join(bin, 'py')+' -m pdb'),
-    usage: pdb.py scriptfile [arg] ...
+    >>> run(join(bin, 'py')+' -m pdb') # doctest: +ELLIPSIS
+    usage: pdb.py ...
 
-    >>> print system(join(bin, 'py')+' -m pdb what'),
+    >>> run(join(bin, 'py')+' -m pdb what')
     Error: what does not exist
 
 An additional argument can be passed to define which scripts to install
@@ -818,7 +813,7 @@
     >>> ls(bin)
     -  run
 
-    >>> print system(os.path.join(bin, 'run')),
+    >>> run(os.path.join(bin, 'run'))
     3 1
 
 The ``scripts`` function: Including extra paths in scripts
@@ -948,7 +943,7 @@
 
 Of course, running the script works:
 
-    >>> print system(join(bo, 'bin', 'run')),
+    >>> run(join(bo, 'bin', 'run'))
     3 1
 
 We specified an interpreter and its paths are adjusted too:
@@ -979,7 +974,7 @@
             if _opt == '-i':
                 _interactive = True
             elif _opt == '-c':
-                exec _val
+                exec(_val)
             elif _opt == '-m':
                 sys.argv[1:] = _args
                 _args = []
@@ -990,7 +985,7 @@
             sys.argv[:] = _args
             __file__ = _args[0]
             del _options, _args
-            execfile(__file__)
+            exec(compile(open(__file__).read(), __file__, "exec"))
     <BLANKLINE>
     if _interactive:
         del _interactive
@@ -1088,7 +1083,7 @@
 behavior of the function it replaces.  The following shows the part that
 buildout inserts, in the simplest case.
 
-    >>> sys.stdout.write('#\n'); cat(site_path)
+    >>> print_('#\n'); cat(site_path)
     ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
     #...
     def addsitepackages(known_paths):
@@ -1110,11 +1105,13 @@
 
 Here are some examples of the interpreter in use.
 
-    >>> print call_py(interpreter_path, "print 16+26")
+    >>> print_(call_py(interpreter_path, "print(16+26)"))
     42
-    <BLANKLINE>
-    >>> res = call_py(interpreter_path, "import sys; print sys.path")
-    >>> print res # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+
+    >>> res = call_py(
+    ...    interpreter_path,
+    ...    "import sys; print([s for s in sys.path])")
+    >>> print(res) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
     ['',
      '/interpreter/parts/interpreter',
      ...,
@@ -1144,7 +1141,8 @@
     >>> cat(sitecustomize_path)
     import os
     os.environ['FOO'] = 'bar baz bing shazam'
-    >>> print call_py(interpreter_path, "import os; print os.environ['FOO']")
+    >>> print(call_py(interpreter_path,
+    ...      "import os; print(os.environ['FOO'])"))
     bar baz bing shazam
     <BLANKLINE>
 
@@ -1177,7 +1175,7 @@
 paths join a base to a path, as with the use of this argument in the
 ``scripts`` function.
 
-    >>> sys.stdout.write('#\n'); cat(site_path) # doctest: +ELLIPSIS
+    >>> print_('#\n'); cat(site_path) # doctest: +ELLIPSIS
     #...
     def addsitepackages(known_paths):
         """Add site packages, as determined by zc.buildout.
@@ -1194,8 +1192,8 @@
 
 The paths resolve in practice as you would expect.
 
-    >>> print call_py(interpreter_path,
-    ...               "import sys, pprint; pprint.pprint(sys.path)")
+    >>> print(call_py(interpreter_path,
+    ...   "import sys, pprint; pprint.pprint([s for s in sys.path])"))
     ... # doctest: +ELLIPSIS
     ['',
      '/interpreter/parts/interpreter',
@@ -1212,7 +1210,7 @@
     >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts(
     ...     interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir,
     ...     interpreter='py', extra_paths=[join(interpreter_dir, 'other')])
-    >>> sys.stdout.write('#\n'); cat(site_path) # doctest: +ELLIPSIS
+    >>> print_('#\n'); cat(site_path) # doctest: +ELLIPSIS
     #...
     def addsitepackages(known_paths):
         """Add site packages, as determined by zc.buildout.
@@ -1224,8 +1222,8 @@
             '/interpreter/other'
             ]...
 
-    >>> print call_py(interpreter_path,
-    ...               "import sys, pprint; pprint.pprint(sys.path)")
+    >>> print(call_py(interpreter_path,
+    ...               "import sys, pprint; pprint.pprint(sys.path)"))
     ... # doctest: +ELLIPSIS
     ['',
      '/interpreter/parts/interpreter',
@@ -1270,7 +1268,7 @@
     >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts(
     ...     interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir,
     ...     interpreter='py', include_site_packages=True)
-    >>> sys.stdout.write('#\n'); cat(site_path)
+    >>> print_('#\n'); cat(site_path)
     ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
     #...
     def addsitepackages(known_paths):
@@ -1305,8 +1303,8 @@
 this package give the feature a more thorough workout, but this should
 give you an idea of the feature.
 
-    >>> res = call_py(interpreter_path, "import sys; print sys.path")
-    >>> print res # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+    >>> res = call_py(interpreter_path, "import sys; print(sys.path)")
+    >>> print(res) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
     ['',
      '/interpreter/parts/interpreter',
      ...,
@@ -1342,7 +1340,7 @@
     >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts(
     ...     interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir,
     ...     interpreter='py', include_site_packages=True)
-    >>> sys.stdout.write('#\n'); cat(site_path)
+    >>> print_('#\n'); cat(site_path)
     ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
     #...
     def addsitepackages(known_paths):
@@ -1376,7 +1374,7 @@
     <BLANKLINE>
     def original_addsitepackages(known_paths):...
 
-    >>> print call_py(interpreter_path, "import sys; print sys.path")
+    >>> print(call_py(interpreter_path, "import sys; print(sys.path)"))
     ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
     ['',
      '/interpreter/parts/interpreter',
@@ -1403,7 +1401,7 @@
     ...     interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir,
     ...     interpreter='py', include_site_packages=True,
     ...     relative_paths=interpreter_dir)
-    >>> sys.stdout.write('#\n'); cat(site_path)
+    >>> print_('#\n'); cat(site_path)
     ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
     #...
     def addsitepackages(known_paths):
@@ -1441,7 +1439,7 @@
     <BLANKLINE>
     def original_addsitepackages(known_paths):...
 
-    >>> print call_py(interpreter_path, "import sys; print sys.path")
+    >>> print(call_py(interpreter_path, "import sys; print(sys.path)"))
     ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
     ['',
      '/interpreter/parts/interpreter',
@@ -1523,9 +1521,8 @@
     >>> demo_call = join(interpreter_bin_dir, 'demo')
     >>> if sys.platform == 'win32':
     ...     demo_call = '"%s"' % demo_call
-    >>> print system(demo_call)
+    >>> run(demo_call)
     3 1
-    <BLANKLINE>
 
 There are a few differences from the ``scripts`` function.  First, the
 ``reqs`` argument (an iterable of string requirements or entry point
@@ -1680,7 +1677,7 @@
 Let's update our link server with a new version of extdemo:
 
     >>> update_extdemo()
-    >>> print get(link_server),
+    >>> print_(get(link_server))
     <html><body>
     <a href="bigdemo-0.1-py2.4.egg">bigdemo-0.1-py2.4.egg</a><br>
     <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br>

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/extends-cache.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/extends-cache.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/extends-cache.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -41,20 +41,20 @@
 When trying to run this buildout offline, we'll find that we cannot read all
 of the required configuration:
 
->>> print system(buildout + ' -o')
+>>> run(buildout + ' -o')
 While:
   Initializing.
 Error: Couldn't download 'http://localhost/base.cfg' in offline mode.
 
 Trying the same online, we can:
 
->>> print system(buildout)
+>>> run(buildout)
 Unused options for buildout: 'foo'.
 
 As long as we haven't said anything about caching downloaded configuration,
 nothing gets cached. Offline mode will still cause the buildout to fail:
 
->>> print system(buildout + ' -o')
+>>> run(buildout + ' -o')
 While:
   Initializing.
 Error: Couldn't download 'http://localhost/base.cfg' in offline mode.
@@ -73,7 +73,7 @@
 ... extends-cache = cache
 ... """ % server_url)
 
->>> print system(buildout)
+>>> run(buildout)
 Unused options for buildout: 'foo'.
 
 >>> cache = join(sample_buildout, 'cache')
@@ -88,7 +88,7 @@
 
 We can now run buildout offline as it will read base.cfg from the cache:
 
->>> print system(buildout + ' -o')
+>>> run(buildout + ' -o')
 Unused options for buildout: 'foo'.
 
 The cache is being used purely as a fall-back in case we are offline or don't
@@ -104,18 +104,18 @@
 ... bar = baz
 ... """)
 
->>> print system(buildout + ' -o')
+>>> run(buildout + ' -o')
 Unused options for buildout: 'foo'.
 
 In online mode, buildout will download and use the modified version:
 
->>> print system(buildout)
+>>> run(buildout)
 Unused options for buildout: 'bar'.
 
 Trying offline mode again, the new version will be used as it has been put in
 the cache now:
 
->>> print system(buildout + ' -o')
+>>> run(buildout + ' -o')
 Unused options for buildout: 'bar'.
 
 Clean up:
@@ -203,7 +203,7 @@
 Buildout will now assemble its configuration from all of these 6 files,
 defaults first. The online resources end up in the respective extends caches:
 
->>> print system(buildout)
+>>> run(buildout)
 Unused options for buildout: 'foo'.
 
 >>> ls('user-cache')
@@ -249,7 +249,7 @@
 >>> remove('user-cache', os.listdir('user-cache')[0])
 >>> remove('cache', os.listdir('cache')[0])
 
->>> print system(buildout)
+>>> run(buildout)
 Unused options for buildout: 'foo'.
 
 >>> ls('user-cache')
@@ -272,7 +272,7 @@
 If we run buildout in offline mode now, it will fail because it cannot get at
 the remote configuration file needed by the user's defaults:
 
->>> print system(buildout + ' -o')
+>>> run(buildout + ' -o')
 While:
   Initializing.
 Error: Couldn't download 'http://localhost/base_default.cfg' in offline mode.
@@ -285,7 +285,7 @@
 ... extends = fancy_default.cfg
 ... offline = true
 ... """)
->>> print system(buildout)
+>>> run(buildout)
 While:
   Initializing.
 Error: Couldn't download 'http://localhost/base_default.cfg' in offline mode.
@@ -299,7 +299,7 @@
 ... extends = %sbase_default.cfg
 ... offline = true
 ... """ % server_url)
->>> print system(buildout)
+>>> run(buildout)
 While:
   Initializing.
 Error: Couldn't download 'http://localhost/base.cfg' in offline mode.
@@ -313,7 +313,7 @@
 ... extends = fancy.cfg
 ... offline = true
 ... """)
->>> print system(buildout)
+>>> run(buildout)
 While:
   Initializing.
 Error: Couldn't download 'http://localhost/base.cfg' in offline mode.
@@ -327,7 +327,7 @@
 ... extends = %sbase.cfg
 ... offline = true
 ... """ % server_url)
->>> print system(buildout)
+>>> run(buildout)
 Unused options for buildout: 'foo'.
 
 The ``install-from-cache`` option is treated accordingly:
@@ -337,7 +337,7 @@
 ... extends = fancy_default.cfg
 ... install-from-cache = true
 ... """)
->>> print system(buildout)
+>>> run(buildout)
 While:
   Initializing.
 Error: Couldn't download 'http://localhost/base_default.cfg' in offline mode.
@@ -351,7 +351,7 @@
 ... extends = %sbase_default.cfg
 ... install-from-cache = true
 ... """ % server_url)
->>> print system(buildout)
+>>> run(buildout)
 While:
   Initializing.
 Error: Couldn't download 'http://localhost/base.cfg' in offline mode.
@@ -365,7 +365,7 @@
 ... extends = fancy.cfg
 ... install-from-cache = true
 ... """)
->>> print system(buildout)
+>>> run(buildout)
 While:
   Initializing.
 Error: Couldn't download 'http://localhost/base.cfg' in offline mode.
@@ -379,7 +379,7 @@
 ... extends = %sbase.cfg
 ... install-from-cache = true
 ... """ % server_url)
->>> print system(buildout)
+>>> run(buildout)
 While:
   Installing.
   Checking for upgrades.
@@ -406,7 +406,7 @@
 ... extends-cache = cache
 ... extends = %sbase.cfg
 ... """ % server_url)
->>> print system(buildout)
+>>> run(buildout)
 >>> ls('cache')
 -  5aedc98d7e769290a29d654a591a3a45
 >>> cat('cache', os.listdir(cache)[0])
@@ -420,7 +420,7 @@
 ... parts =
 ... foo = bar
 ... """)
->>> print system(buildout + " -n")
+>>> run(buildout + " -n")
 Unused options for buildout: 'foo'.
 >>> cat('cache', os.listdir(cache)[0])
 [buildout]
@@ -434,7 +434,7 @@
 ... [buildout]
 ... parts =
 ... """)
->>> print system(buildout + " -N")
+>>> run(buildout + " -N")
 Unused options for buildout: 'foo'.
 >>> cat('cache', os.listdir(cache)[0])
 [buildout]
@@ -463,7 +463,7 @@
 ... newest = true
 ... extends = %sbaseA.cfg %sbaseB.cfg
 ... """ % (server_url, server_url))
->>> print system(buildout + " -n")
+>>> run(buildout + " -n")
 Unused options for buildout: 'bar' 'foo'.
 
 (XXX We patch download utility's API to produce readable output for the test;
@@ -472,7 +472,7 @@
 >>> import zc.buildout
 >>> old_download = zc.buildout.download.Download.download
 >>> def wrapper_download(self, url, md5sum=None, path=None):
-...   print "The URL %s was downloaded." % url
+...   print("The URL %s was downloaded." % url)
 ...   return old_download(url, md5sum, path)
 >>> zc.buildout.download.Download.download = wrapper_download
 
@@ -498,7 +498,7 @@
 ... parts =
 ... extended-by = foo.cfg
 ... """)
->>> print system(buildout)
+>>> run(buildout)
 While:
   Initializing.
 Error: No-longer supported "extended-by" option found in http://localhost/base.cfg.

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/repeatable.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/repeatable.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/repeatable.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -24,7 +24,7 @@
     ... class Recipe:
     ...     def __init__(*a): pass
     ...     def install(self):
-    ...         print 'recipe v1'
+    ...         print('recipe v1')
     ...         return ()
     ...     update = install
     ... ''')
@@ -39,7 +39,7 @@
 
     >>> write('recipe', 'README', '')
 
-    >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS
+    >>> run(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS
     Running setup script 'recipe/setup.py'.
     ...
 
@@ -50,7 +50,7 @@
     ... class Recipe:
     ...     def __init__(*a): pass
     ...     def install(self):
-    ...         print 'recipe v2'
+    ...         print('recipe v2')
     ...         return ()
     ...     update = install
     ... ''')
@@ -64,7 +64,7 @@
     ... ''')
 
 
-    >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS
+    >>> run(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS
     Running setup script 'recipe/setup.py'.
     ...
 
@@ -82,7 +82,7 @@
 
 If we run the buildout, it will use version 2:
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Getting distribution for 'spam'.
     Got spam 2.
     Installing foo.
@@ -112,7 +112,7 @@
 
 Now, if we run the buildout, we'll use version 1 of the spam recipe:
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Getting distribution for 'spam==1'.
     Got spam 1.
     Uninstalling foo.
@@ -123,7 +123,7 @@
 about versions used. If we run the buildout in verbose mode without
 specifying a versions section:
 
-    >>> print system(buildout+' buildout:versions= -v'), # doctest: +ELLIPSIS
+    >>> run(buildout+' buildout:versions= -v') # doctest: +ELLIPSIS
     Installing 'zc.buildout', 'setuptools'.
     We have a develop egg: zc.buildout 1.0.0.
     We have the best distribution that satisfies 'setuptools'.
@@ -145,7 +145,7 @@
 
 If we run the buildout with the versions section:
 
-    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    >>> run(buildout+' -v') # doctest: +ELLIPSIS
     Installing 'zc.buildout', 'setuptools'.
     We have a develop egg: zc.buildout 1.0.0.
     We have the best distribution that satisfies 'setuptools'.

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/rmtree.py
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/rmtree.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/rmtree.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -54,7 +54,7 @@
     0
     """
     def retry_writeable (func, path, exc):
-        os.chmod (path, 0600)
+        os.chmod (path, 0o600)
         func (path)
 
     shutil.rmtree (path, onerror = retry_writeable)

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/runsetup.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/runsetup.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/runsetup.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -17,7 +17,7 @@
 To illustrate this, we'll create a package in a sample buildout:
 
     >>> mkdir('hello')
-    >>> write('hello', 'hello.py', 'print "Hello World!"')
+    >>> write('hello', 'hello.py', 'print("Hello World!")')
     >>> write('hello', 'README', 'This is hello')
     >>> write('hello', 'setup.py',
     ... """
@@ -29,10 +29,10 @@
     ...       author_email="bob at foo.com",
     ...       )
     ... """)
-  
+
 We can use the buildout command to generate the hello egg:
 
-    >>> print system(buildout +' setup hello -q bdist_egg'),
+    >>> run(buildout +' setup hello -q bdist_egg')
     Running setup script 'hello/setup.py'.
     zip_safe flag not set; analyzing archive contents...
 

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/setup.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/setup.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/setup.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -28,14 +28,14 @@
 doesn't import setuptools.  Let's try running it to create an egg.
 We'll use the buildout script from our sample buildout:
 
-    >>> print system(buildout+' setup'),
+    >>> run(buildout+' setup')
     ... # doctest: +NORMALIZE_WHITESPACE
     Error: The setup command requires the path to a setup script or
     directory containing a setup script, and its arguments.
 
 Oops, we forgot to give the name of the setup script:
 
-    >>> print system(buildout+' setup setup.py bdist_egg'),
+    >>> run(buildout+' setup setup.py bdist_egg')
     ... # doctest: +ELLIPSIS
     Running setup script 'setup.py'.
     ...
@@ -46,6 +46,6 @@
 Note that we can specify a directory name.  This is often shorter and
 preferred by the lazy :)
 
-    >>> print system(buildout+' setup . bdist_egg'), # doctest: +ELLIPSIS
+    >>> run(buildout+' setup . bdist_egg') # doctest: +ELLIPSIS
     Running setup script './setup.py'.
     ...

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/testing.py
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/testing.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/testing.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -12,11 +12,9 @@
 #
 ##############################################################################
 """Various test-support utility functions
-
-$Id$
 """
 
-import BaseHTTPServer
+import http.server
 import errno
 import logging
 import os
@@ -31,10 +29,11 @@
 import textwrap
 import threading
 import time
-import urllib2
+import urllib.request, urllib.error, urllib.parse
 
 import zc.buildout.buildout
 import zc.buildout.easy_install
+from zc.buildout.easy_install import setuptools_key
 from zc.buildout.rmtree import rmtree
 
 fsync = getattr(os, 'fsync', lambda fileno: None)
@@ -62,7 +61,7 @@
         and os.path.exists(path+'-script.py')
         ):
         path = path+'-script.py'
-    print open(path).read(),
+    sys.stdout.write(open(path).read())
 
 def ls(dir, *subs):
     if subs:
@@ -70,13 +69,15 @@
     names = os.listdir(dir)
     names.sort()
     for name in names:
+        if name == '__pycache__':
+            continue
         if os.path.isdir(os.path.join(dir, name)):
-            print 'd ',
+            print('d ', end=' ')
         elif os.path.islink(os.path.join(dir, name)):
-            print 'l ',
+            print('l ', end=' ')
         else:
-            print '- ',
-        print name
+            print('- ', end=' ')
+        print(name)
 
 def mkdir(*path):
     os.mkdir(os.path.join(*path))
@@ -115,13 +116,19 @@
                          )
     i, o, e = (p.stdin, p.stdout, p.stderr)
     if input:
-        i.write(input)
+        i.write(input.encode())
     i.close()
     result = o.read() + e.read()
     o.close()
     e.close()
-    return result
+    return result.decode()
 
+def print_(*args):
+    sys.stdout.write(' '.join(map(str, args)))
+
+def run(command, input=''):
+    sys.stdout.write(system(command, input))
+
 def call_py(interpreter, cmd, flags=None):
     if sys.platform == 'win32':
         args = ['"%s"' % arg for arg in (interpreter, flags, cmd) if arg]
@@ -133,7 +140,7 @@
             ' '.join(arg for arg in (interpreter, flags, '-c', cmd) if arg))
 
 def get(url):
-    return urllib2.urlopen(url).read()
+    return urllib.request.urlopen(url).read().decode()
 
 def _runsetup(setup, executable, *args):
     if os.path.isdir(setup):
@@ -173,7 +180,7 @@
 
 def find_python(version):
     env_friendly_version = ''.join(version.split('.'))
-    
+
     e = os.environ.get('PYTHON%s' % env_friendly_version)
     if e is not None:
         return e
@@ -182,7 +189,7 @@
         if os.path.exists(e):
             return e
     else:
-        cmd = 'python%s -c "import sys; print sys.executable"' % version
+        cmd = 'python%s -c "import sys; print(sys.executable)"' % version
         p = subprocess.Popen(cmd,
                              shell=True,
                              stdin=subprocess.PIPE,
@@ -195,7 +202,7 @@
         o.close()
         if os.path.exists(e):
             return e
-        cmd = 'python -c "import sys; print \'%s.%s\' % sys.version_info[:2]"'
+        cmd = 'python -c "import sys; print(\'%s.%s\' % sys.version_info[:2])"'
         p = subprocess.Popen(cmd,
                              shell=True,
                              stdin=subprocess.PIPE,
@@ -207,7 +214,7 @@
         e = o.read().strip()
         o.close()
         if e == version:
-            cmd = 'python -c "import sys; print sys.executable"'
+            cmd = 'python -c "import sys; print(sys.executable)"'
             p = subprocess.Popen(cmd,
                                 shell=True,
                                 stdin=subprocess.PIPE,
@@ -241,6 +248,26 @@
         time.sleep(0.01)
     raise ValueError('Timed out waiting for: '+label)
 
+def raises(exc_type, callable, *args, **kw):
+    if isinstance(exc_type, str):
+        E = Exception
+    else:
+        E = exc_type
+
+    try:
+        callable(*args, **kw)
+    except E:
+        v = sys.exc_info()[1]
+        if E is exc_type:
+            return v
+
+        if exc_type == v.__class__.__name__:
+            return v
+        else:
+            raise
+
+    raise AssertionError("Expected %r" % exc_type)
+
 def get_installer_values():
     """Get the current values for the easy_install module.
 
@@ -260,7 +287,7 @@
 
 def set_installer_values(values):
     """Set the given values on the installer."""
-    for name, value in values.items():
+    for name, value in list(values.items()):
         getattr(zc.buildout.easy_install, name)(value)
 
 def make_buildout(executable=None):
@@ -378,7 +405,7 @@
             'zc.recipe.egg', os.path.join(buildout, 'develop-eggs'))
         install_develop(
             'z3c.recipe.scripts', os.path.join(buildout, 'develop-eggs'))
-        write('buildout.cfg', textwrap.dedent('''\
+        write('buildout.cfg', textwrap.dedent('''
             [buildout]
             parts = py
             include-site-packages = false
@@ -389,11 +416,14 @@
             interpreter = py
             initialization =
             %(initialization)s
-            extra-paths = %(site-packages)s
-            eggs = setuptools
-            ''') % {
-                'initialization': initialization,
-                'site-packages': site_packages_dir})
+            extra-paths = %(site_packages)s
+            eggs = %(setuptools_key)s
+            ''') % dict(
+                  initialization = initialization,
+                  site_packages = site_packages_dir,
+                  setuptools_key = setuptools_key,
+                  ),
+              )
         system(os.path.join(buildout, 'bin', 'buildout'))
         os.chdir(old_wd)
         return (
@@ -409,6 +439,9 @@
         tmpdir = tmpdir,
         write = write,
         system = system,
+        run = run,
+        raises = raises,
+        print_ = print_,
         call_py = call_py,
         get = get,
         cd = (lambda *path: os.chdir(os.path.join(*path))),
@@ -425,10 +458,10 @@
     for f in test.globs['__tear_downs']:
         f()
 
-class Server(BaseHTTPServer.HTTPServer):
+class Server(http.server.HTTPServer):
 
     def __init__(self, tree, *args):
-        BaseHTTPServer.HTTPServer.__init__(self, *args)
+        http.server.HTTPServer.__init__(self, *args)
         self.tree = os.path.abspath(tree)
 
     __run = True
@@ -439,14 +472,14 @@
     def handle_error(self, *_):
         self.__run = False
 
-class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
+class Handler(http.server.BaseHTTPRequestHandler):
 
     Server.__log = False
 
     def __init__(self, request, address, server):
         self.__server = server
         self.tree = server.tree
-        BaseHTTPServer.BaseHTTPRequestHandler.__init__(
+        http.server.BaseHTTPRequestHandler.__init__(
             self, request, address, server)
 
     def do_GET(self):
@@ -470,9 +503,7 @@
             os.path.exists(path)
             ):
             self.send_response(404, 'Not Found')
-            #self.send_response(200)
-            out = '<html><body>Not Found</body></html>'
-            #out = '\n'.join(self.tree, self.path, path)
+            out = '<html><body>Not Found</body></html>'.encode()
             self.send_header('Content-Length', str(len(out)))
             self.send_header('Content-Type', 'text/html')
             self.end_headers()
@@ -489,7 +520,7 @@
                     name += '/'
                 out.append('<a href="%s">%s</a><br>\n' % (name, name))
             out.append('</body></html>\n')
-            out = ''.join(out)
+            out = ''.join(out).encode()
             self.send_header('Content-Length', str(len(out)))
             self.send_header('Content-Type', 'text/html')
         else:
@@ -509,7 +540,7 @@
 
     def log_request(self, code):
         if self.__server.__log:
-            print '%s %s %s' % (self.command, code, self.path)
+            print('%s %s %s' % (self.command, code, self.path))
 
 def _run(tree, port):
     server_address = ('localhost', port)
@@ -527,7 +558,7 @@
                 return port
         finally:
             s.close()
-    raise RuntimeError, "Can't find port"
+    raise RuntimeError("Can't find port")
 
 def _start_server(tree, name=''):
     port = get_port()
@@ -542,7 +573,7 @@
 
 def stop_server(url, thread=None):
     try:
-        urllib2.urlopen(url+'__stop__')
+        urllib.request.urlopen(url+'__stop__')
     except Exception:
         pass
     if thread is not None:
@@ -558,7 +589,7 @@
             s.close()
             if up:
                 break
-        except socket.error, e:
+        except socket.error as e:
             if e[0] not in (errno.ECONNREFUSED, errno.ECONNRESET):
                 raise
             s.close()
@@ -571,7 +602,7 @@
             raise SystemError("Couln't stop server")
 
 def install(project, destination):
-    if not isinstance(destination, basestring):
+    if not isinstance(destination, str):
         destination = os.path.join(destination.globs['sample_buildout'],
                                    'eggs')
 
@@ -591,7 +622,7 @@
              ).write(dist.location)
 
 def install_develop(project, destination):
-    if not isinstance(destination, basestring):
+    if not isinstance(destination, str):
         destination = os.path.join(destination.globs['sample_buildout'],
                                    'develop-eggs')
 

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/testrecipes.py
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/testrecipes.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/testrecipes.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -7,10 +7,10 @@
         self.options = options
 
     def install(self):
-        items = self.options.items()
+        items = list(self.options.items())
         items.sort()
         for option, value in items:
-            print "  %s=%r" % (option, value)
+            print("  %s=%r" % (option, value))
         return ()
 
     update = install

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/tests.py
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/tests.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/tests.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -11,6 +11,8 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
+from zc.buildout.easy_install import setuptools_key
+
 import doctest
 from zope.testing import renormalizing
 import os
@@ -47,7 +49,7 @@
     ... parts =
     ... ''')
 
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
     Develop: '/sample-buildout/foo'
 
     >>> ls('develop-eggs')
@@ -75,7 +77,7 @@
     ... parts =
     ... ''')
 
-    >>> print system(join('bin', 'buildout')+' -vv'), # doctest: +ELLIPSIS
+    >>> run(join('bin', 'buildout')+' -vv') # doctest: +ELLIPSIS
     Installing...
     Develop: '/sample-buildout/foo'
     ...
@@ -87,7 +89,7 @@
     -  z3c.recipe.scripts.egg-link
     -  zc.recipe.egg.egg-link
 
-    >>> print system(join('bin', 'buildout')+' -vvv'), # doctest: +ELLIPSIS
+    >>> run(join('bin', 'buildout')+' -vvv') # doctest: +ELLIPSIS
     Installing...
     Develop: '/sample-buildout/foo'
     in: '/sample-buildout/foo'
@@ -105,17 +107,13 @@
     >>> os.chdir(sample_buildout)
     >>> import zc.buildout.buildout
     >>> buildout = zc.buildout.buildout.Buildout('buildout.cfg', [])
-    >>> buildout['eek']
-    Traceback (most recent call last):
-    ...
-    MissingSection: The referenced section, 'eek', was not defined.
+    >>> print(raises('MissingSection', buildout.__getitem__, 'eek'))
+    The referenced section, 'eek', was not defined.
 
 Asking for an option that doesn't exist, a MissingOption error is raised:
 
-    >>> buildout['buildout']['eek']
-    Traceback (most recent call last):
-    ...
-    MissingOption: Missing option: buildout:eek
+    >>> print(raises('MissingOption', buildout['buildout'].__getitem__, 'eek'))
+    Missing option: buildout:eek
 
 It is an error to create a variable-reference cycle:
 
@@ -150,7 +148,7 @@
     ... x = ${bui$ldout:y}
     ... ''')
 
-    >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
+    >>> run(os.path.join(sample_buildout, 'bin', 'buildout'))
     While:
       Initializing.
       Getting section buildout.
@@ -167,7 +165,7 @@
     ... x = ${buildout:y{z}
     ... ''')
 
-    >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
+    >>> run(os.path.join(sample_buildout, 'bin', 'buildout'))
     While:
       Initializing.
       Getting section buildout.
@@ -186,7 +184,7 @@
     ... x = ${parts}
     ... ''')
 
-    >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
+    >>> run(os.path.join(sample_buildout, 'bin', 'buildout'))
     While:
       Initializing.
       Getting section buildout.
@@ -203,7 +201,7 @@
     ... x = ${buildout:y:z}
     ... ''')
 
-    >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
+    >>> run(os.path.join(sample_buildout, 'bin', 'buildout'))
     While:
       Initializing.
       Getting section buildout.
@@ -220,7 +218,7 @@
     ... parts = x
     ... ''')
 
-    >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
+    >>> run(os.path.join(sample_buildout, 'bin', 'buildout'))
     While:
       Installing.
       Getting section x.
@@ -238,7 +236,7 @@
     ... foo = 1
     ... ''')
 
-    >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
+    >>> run(os.path.join(sample_buildout, 'bin', 'buildout'))
     While:
       Installing.
     Error: Missing option: x:recipe
@@ -287,7 +285,7 @@
     ...        samplez
     ... ''' % globals())
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/sampley'
     Develop: '/sample-buildout/samplez'
     Installing eggs.
@@ -320,7 +318,7 @@
 
 If we use the verbose switch, we can see where requirements are coming from:
 
-    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    >>> run(buildout+' -v') # doctest: +ELLIPSIS
     Installing 'zc.buildout', 'setuptools'.
     We have a develop egg: zc.buildout 1.0.0
     We have the best distribution that satisfies 'setuptools'.
@@ -371,7 +369,7 @@
     ... eggs = samplea
     ... ''')
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/sampley'
     Develop: '/sample-buildout/samplea'
     Develop: '/sample-buildout/sampleb'
@@ -419,7 +417,7 @@
 indicate the eggs from site-packages that have been selected.  You'll see
 we have two: demo 0.3 and demoneeded 1.1.
 
-    >>> print system(buildout+" -v"),
+    >>> run(buildout+" -v")
     Installing 'zc.buildout', 'setuptools'.
     We have a develop egg: zc.buildout V
     We have the best distribution that satisfies 'setuptools'.
@@ -505,14 +503,14 @@
     >>> os.chdir(sample_buildout)
     >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Installing debug.
 
 If we run the buildout again, we shoudn't get a message about
 uninstalling anything because the configuration hasn't changed.
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Updating debug.
 """
@@ -576,7 +574,7 @@
     >>> write('demo', 'demo.py',
     ... '''
     ... def main():
-    ...     print 'Python 2.5'
+    ...     print('Python 2.5')
     ... ''')
 
     >>> write('buildout.cfg',
@@ -586,7 +584,7 @@
     ... parts =
     ... ''')
 
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
     Develop: '/sample-buildout/demo'
 
     >>> import zc.buildout.easy_install
@@ -596,7 +594,7 @@
     ...      ['demo'], ws, sys.executable, 'bin'))
     True
 
-    >>> print system(join('bin', 'demo')),
+    >>> run(join('bin', 'demo'))
     Python 2.5
 
 Now, finally, let's test _get_version:
@@ -615,7 +613,7 @@
     ... x = ${foo:bar}
     ... ''')
 
-    >>> print system(buildout + ' foo:bar=1 -vv'), # doctest: +ELLIPSIS
+    >>> run(buildout + ' foo:bar=1 -vv') # doctest: +ELLIPSIS
     Installing 'zc.buildout', 'setuptools'.
     ...
     [foo]
@@ -626,7 +624,7 @@
 
 def test_help():
     """
-    >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')+' -h'),
+    >>> run(os.path.join(sample_buildout, 'bin', 'buildout')+' -h')
     ... # doctest: +ELLIPSIS
     Usage: buildout [options] [assignments] [command [command arguments]]
     <BLANKLINE>
@@ -635,8 +633,7 @@
       -h, --help
     ...
 
-    >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')
-    ...              +' --help'),
+    >>> run(os.path.join(sample_buildout, 'bin', 'buildout') +' --help')
     ... # doctest: +ELLIPSIS
     Usage: buildout [options] [assignments] [command [command arguments]]
     <BLANKLINE>
@@ -662,8 +659,7 @@
     ... ''')
 
     >>> os.chdir(d)
-    >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')
-    ...              + ' bootstrap'),
+    >>> run(os.path.join(sample_buildout, 'bin', 'buildout') + ' bootstrap')
     Creating directory '/sample-bootstrap/bin'.
     Creating directory '/sample-bootstrap/parts'.
     Creating directory '/sample-bootstrap/eggs'.
@@ -689,15 +685,14 @@
     ... ''')
 
     >>> os.chdir(d)
-    >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')
-    ...              + ' bootstrap'),
+    >>> run(os.path.join(sample_buildout, 'bin', 'buildout') + ' bootstrap')
     Creating directory '/sample-bootstrap/bin'.
     Creating directory '/sample-bootstrap/parts'.
     Creating directory '/sample-bootstrap/eggs'.
     Creating directory '/sample-bootstrap/develop-eggs'.
     Generated script '/sample-bootstrap/bin/buildout'.
 
-    >>> print system(os.path.join('bin', 'buildout')),
+    >>> run(os.path.join('bin', 'buildout'))
     Unused options for buildout: 'scripts' 'eggs'.
 
     """
@@ -721,7 +716,7 @@
     ... parts =
     ... """)
 
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
     Develop: '/sample-buildout/foo'
 
     >>> ls('develop-eggs')
@@ -744,7 +739,7 @@
     ... parts =
     ... """)
 
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
     Develop: '/sample-buildout/foo'
     Develop: '/sample-buildout/bar'
 
@@ -762,7 +757,7 @@
     ... develop = bar
     ... parts =
     ... """)
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
     Develop: '/sample-buildout/bar'
 
 It is gone
@@ -779,7 +774,7 @@
     ... [buildout]
     ... parts =
     ... """)
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
 
 All gone
 
@@ -825,7 +820,7 @@
     ... parts =
     ... """)
 
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
     Develop: '/sample-buildout/foo'
 
 Now, if we generate a working set using the egg link, we will get a warning
@@ -844,7 +839,7 @@
     ...     ])]
     ['foox', 'setuptools']
 
-    >>> print handler
+    >>> print(handler)
     zc.buildout.easy_install WARNING
       Develop distribution: foox 0.0.0
     uses namespace packages but the distribution does not require setuptools.
@@ -862,7 +857,7 @@
     -  z3c.recipe.scripts.egg-link
     -  zc.recipe.egg.egg-link
 
-    >>> print 'START ->'; ls('eggs') # doctest: +ELLIPSIS
+    >>> print('START ->'); ls('eggs') # doctest: +ELLIPSIS
     START...
     -  foox-0.0.0-py2.4.egg
     ...
@@ -877,7 +872,7 @@
     ...     ])]
     ['foox', 'setuptools']
 
-    >>> print handler,
+    >>> print_(handler)
 
 We get the same behavior if the it is a depedency that uses a
 namespace package.
@@ -898,7 +893,7 @@
     ... parts =
     ... """)
 
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
     Develop: '/sample-buildout/foo'
     Develop: '/sample-buildout/bar'
 
@@ -910,7 +905,7 @@
     ...     ])]
     ['bar', 'foox', 'setuptools']
 
-    >>> print handler,
+    >>> print_(handler)
     zc.buildout.easy_install WARNING
       Develop distribution: foox 0.0.0
     uses namespace packages but the distribution does not require setuptools.
@@ -986,9 +981,9 @@
     ... class Install:
     ...     def __init__(*args): pass
     ...     def install(self):
-    ...         print 'installing'
+    ...         print('installing')
     ...         return ()
-    ... def uninstall(name, options): print 'uninstalling'
+    ... def uninstall(name, options): print('uninstalling')
     ... ''')
 
     >>> write('buildout.cfg', '''
@@ -999,7 +994,7 @@
     ... recipe = recipes:demo
     ... ''')
 
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
     Develop: '/sample-buildout/recipes'
     Installing demo.
     installing
@@ -1014,7 +1009,7 @@
     ... x = 1
     ... ''')
 
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
     Develop: '/sample-buildout/recipes'
     Uninstalling demo.
     Running uninstall recipe.
@@ -1029,7 +1024,7 @@
     ... parts =
     ... ''')
 
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
     Develop: '/sample-buildout/recipes'
     Uninstalling demo.
     Running uninstall recipe.
@@ -1044,7 +1039,7 @@
     >>> write('demo', 'demo.py',
     ... """
     ... def ext(buildout):
-    ...     print 'ext', list(buildout)
+    ...     print('ext', list(buildout))
     ... """)
 
     >>> write('demo', 'setup.py',
@@ -1069,7 +1064,7 @@
     ... offline = true
     ... """)
 
-    >>> print system(join(sample_buildout, 'bin', 'buildout')),
+    >>> run(join(sample_buildout, 'bin', 'buildout'))
     ext ['buildout']
 
 
@@ -1107,20 +1102,20 @@
     ... ''')
 
 
-    >>> print system(join(sample_buildout, 'bin', 'buildout')),
+    >>> run(join(sample_buildout, 'bin', 'buildout'))
     Develop: '/sample-buildout/recipe'
     Installing foo.
 
     >>> mkdir('recipe', '.svn')
     >>> mkdir('recipe', 'CVS')
-    >>> print system(join(sample_buildout, 'bin', 'buildout')),
+    >>> run(join(sample_buildout, 'bin', 'buildout'))
     Develop: '/sample-buildout/recipe'
     Updating foo.
 
     >>> write('recipe', '.svn', 'x', '1')
     >>> write('recipe', 'CVS', 'x', '1')
 
-    >>> print system(join(sample_buildout, 'bin', 'buildout')),
+    >>> run(join(sample_buildout, 'bin', 'buildout'))
     Develop: '/sample-buildout/recipe'
     Updating foo.
 
@@ -1159,7 +1154,7 @@
     ... ''')
 
 
-    >>> print system(join(sample_buildout, 'bin', 'buildout')),
+    >>> run(join(sample_buildout, 'bin', 'buildout'))
     Develop: '/sample-buildout/recipe'
     Installing foo.
 
@@ -1176,7 +1171,7 @@
 
     >>> remove('recipe', 'some-file')
 
-    >>> print system(join(sample_buildout, 'bin', 'buildout')),
+    >>> run(join(sample_buildout, 'bin', 'buildout'))
     Develop: '/sample-buildout/recipe'
     Updating foo.
 
@@ -1184,7 +1179,7 @@
 
 def o_option_sets_offline():
     """
-    >>> print system(join(sample_buildout, 'bin', 'buildout')+' -vvo'),
+    >>> run(join(sample_buildout, 'bin', 'buildout')+' -vvo')
     ... # doctest: +ELLIPSIS
     <BLANKLINE>
     ...
@@ -1205,7 +1200,7 @@
     ... class Recipe:
     ...     def __init__(*a): pass
     ...     def install(self):
-    ...         print 'recipe v1'
+    ...         print('recipe v1')
     ...         return ()
     ...     update = install
     ... ''')
@@ -1220,7 +1215,7 @@
 
     >>> write('recipe', 'README', '')
 
-    >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS
+    >>> run(buildout+' setup recipe bdist_egg') # doctest: +ELLIPSIS
     Running setup script 'recipe/setup.py'.
     ...
 
@@ -1238,7 +1233,7 @@
     ... recipe = recipe
     ... ''' % join('recipe', 'dist'))
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Getting distribution for 'recipe'.
     Got recipe 1.
     Installing foo.
@@ -1251,7 +1246,7 @@
     ... class Recipe:
     ...     def __init__(*a): pass
     ...     def install(self):
-    ...         print 'recipe v2'
+    ...         print('recipe v2')
     ...         return ()
     ...     update = install
     ... ''')
@@ -1265,25 +1260,25 @@
     ... ''')
 
 
-    >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS
+    >>> run(buildout+' setup recipe bdist_egg') # doctest: +ELLIPSIS
     Running setup script 'recipe/setup.py'.
     ...
 
 We won't get the update if we specify -N:
 
-    >>> print system(buildout+' -N'),
+    >>> run(buildout+' -N')
     Updating foo.
     recipe v1
 
 or if we use -o:
 
-    >>> print system(buildout+' -o'),
+    >>> run(buildout+' -o')
     Updating foo.
     recipe v1
 
 But we will if we use neither of these:
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Getting distribution for 'recipe'.
     Got recipe 2.
     Uninstalling foo.
@@ -1302,7 +1297,7 @@
     ... recipe = recipe ==1
     ... ''' % join('recipe', 'dist'))
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Uninstalling foo.
     Installing foo.
     recipe v1
@@ -1351,11 +1346,11 @@
     ... recipe = recipe
     ... ''')
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipe'
     Installing foo.
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipe'
     Updating foo.
 
@@ -1387,7 +1382,7 @@
     ...     ['demo==0.2'], dest,
     ...     links=[link_server], index=link_server+'index/')
 
-    >>> print handler # doctest: +ELLIPSIS
+    >>> print(handler) # doctest: +ELLIPSIS
     zc.buildout.easy_install DEBUG
       Installing 'demo==0.2'.
     zc.buildout.easy_install DEBUG
@@ -1433,7 +1428,7 @@
     ... recipe = recipes:mkdir
     ... ''')
 
-    >>> print system(buildout), # doctest: +ELLIPSIS
+    >>> run(buildout) # doctest: +ELLIPSIS
     Develop: '/sample-buildout/recipes'
     While:
       Installing.
@@ -1485,7 +1480,7 @@
     ... z = 1
     ... """)
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/.'
     Unused options for buildout: 'a'.
     Installing foo.
@@ -1553,19 +1548,19 @@
     ... recipe = recipes:clean
     ... ''')
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Installing p1.
     Installing p2.
     Installing p3.
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Updating p1.
     Updating p2.
     Installing p3.
 
-    >>> print system(buildout+' buildout:parts='),
+    >>> run(buildout+' buildout:parts=')
     Develop: '/sample-buildout/recipes'
     Uninstalling p2.
     Uninstalling p1.
@@ -1591,20 +1586,20 @@
     ... recipe = recipes:clean
     ... ''')
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Installing p1.
     Installing p2.
     Installing p3.
     Installing p4.
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Updating p1.
     Updating p2.
     Updating p3.
 
-    >>> print system(buildout+' buildout:parts='),
+    >>> run(buildout+' buildout:parts=')
     Develop: '/sample-buildout/recipes'
     Uninstalling p2.
     Uninstalling p1.
@@ -1632,7 +1627,7 @@
     ... recipe = recipes:clean
     ... ''')
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Installing p1.
     Installing p2.
@@ -1659,7 +1654,7 @@
     ... x = 1
     ... ''')
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling p4.
     Updating p1.
@@ -1683,7 +1678,7 @@
     ... recipe = recipes:clean
     ... ''')
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Uninstalling p1.
     Installing p1.
@@ -1716,7 +1711,7 @@
     ...     zip_safe=False)
     ... ''')
 
-    >>> print system(buildout+' setup badegg sdist'), # doctest: +ELLIPSIS
+    >>> run(buildout+' setup badegg sdist') # doctest: +ELLIPSIS
     Running setup script 'badegg/setup.py'.
     ...
 
@@ -1738,7 +1733,7 @@
     ... scripts = buildout=bo
     ... ''' % globals())
 
-    >>> print system(buildout);print 'X' # doctest: +ELLIPSIS
+    >>> print(system(buildout));print('X') # doctest: +ELLIPSIS
     Installing eggs.
     Getting distribution for 'badegg'.
     Got badegg 1.
@@ -1800,7 +1795,7 @@
     ... eggs = demo
     ... ''' % globals())
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Installing x.
     Getting distribution for 'demo'.
     Got demo 0.4c1.
@@ -1808,7 +1803,7 @@
     Got demoneeded 1.2c1.
     Generated script '/sample-buildout/bin/demo'.
 
-    >>> print system(join('bin', 'demo')),
+    >>> run(join('bin', 'demo'))
     4 2
 
     >>> write('buildout.cfg',
@@ -1822,14 +1817,14 @@
     ... eggs = demo ==0.1
     ... ''' % globals())
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Uninstalling x.
     Installing x.
     Getting distribution for 'demo==0.1'.
     Got demo 0.1.
     Generated script '/sample-buildout/bin/demo'.
 
-    >>> print system(join('bin', 'demo')),
+    >>> run(join('bin', 'demo'))
     1 2
     """
 
@@ -1851,9 +1846,10 @@
 version 0.3 and demoneeded version 1.1.
 
     >>> py_path = make_py_with_system_install(make_py, sample_eggs)
-    >>> print call_py(
+    >>> print_(call_py(
     ...     py_path,
-    ...     "import tellmy.version; print tellmy.version.__version__"),
+    ...     "import tellmy.version; print(tellmy.version.__version__)"
+    ...     ))
     1.1
 
 Now here's a setup that would expose the bug, using the
@@ -1868,7 +1864,7 @@
     >>> for dist in workingset:
     ...     res = str(dist)
     ...     if res.startswith('tellmy.version'):
-    ...         print res
+    ...         print(res)
     ...         break
     tellmy.version 1.0
 
@@ -1888,11 +1884,11 @@
 tellmy.version 1.1, and tellmy.fortune 1.0.  tellmy.version 1.1 is installed.
 
     >>> py_path = make_py_with_system_install(make_py, sample_eggs)
-    >>> print call_py(
+    >>> print_(call_py(
     ...     py_path,
-    ...     "import tellmy.version; print tellmy.version.__version__")
+    ...     "import tellmy.version; print(tellmy.version.__version__)"
+    ...     ))
     1.1
-    <BLANKLINE>
 
 Now we will create a buildout that creates a script and a faux-Python script.
 We want to see that both can successfully import the specified versions of
@@ -1917,12 +1913,12 @@
     ...        demo
     ... script-initialization =
     ...     import tellmy.version
-    ...     print tellmy.version.__version__
+    ...     print(tellmy.version.__version__)
     ...     import tellmy.fortune
-    ...     print tellmy.fortune.__version__
+    ...     print(tellmy.fortune.__version__)
     ... ''' % globals())
 
-    >>> print system(buildout)
+    >>> run(buildout)
     Installing eggs.
     Getting distribution for 'tellmy.version==1.0'.
     Got tellmy.version 1.0.
@@ -1934,7 +1930,6 @@
     Got demoneeded 1.2c1.
     Generated script '/sample-buildout/bin/demo'.
     Generated interpreter '/sample-buildout/bin/py'.
-    <BLANKLINE>
 
 Finally, we are ready to see if it worked.  Prior to the bug fix that
 this tests, the results of both calls below was the following::
@@ -1949,20 +1944,19 @@
 we could not import tellmy.fortune at all.  The following are the correct
 results for the interpreter and for the script.
 
-    >>> print call_py(
+    >>> print(call_py(
     ...     join('bin', 'py'),
     ...     "import tellmy.version; " +
-    ...     "print tellmy.version.__version__; " +
+    ...     "print(tellmy.version.__version__); " +
     ...     "import tellmy.fortune; " +
-    ...     "print tellmy.fortune.__version__") # doctest: +ELLIPSIS
+    ...     "print(tellmy.fortune.__version__)")) # doctest: +ELLIPSIS
     1.0
     1.0...
 
-    >>> print system(join('bin', 'demo'))
+    >>> run(join('bin', 'demo'))
     1.0
     1.0
     4 2
-    <BLANKLINE>
     """
 
 if not zc.buildout.testing.script_in_shebang:
@@ -2006,11 +2000,11 @@
     ...             " name='tellmy.version',\n"
     ...             " package_dir = {'': 'src'},\n"
     ...             " packages = ['tellmy', 'tellmy.version'],\n"
-    ...             " install_requires = ['setuptools'],\n"
+    ...             " install_requires = [%(setuptools_key)r],\n"
     ...             " namespace_packages=['tellmy'],\n"
     ...             " zip_safe=True, version=__version__,\n"
     ...             " author='bob', url='bob', author_email='bob')\n"
-    ...             )
+    ...             % globals())
     ...         zc.buildout.testing.sdist(tmp, sample_eggs)
     ...         if version == '1.0':
     ...             # We install the 1.0 version in site packages the way a
@@ -2018,11 +2012,12 @@
     ...             zc.buildout.testing.sys_install(tmp, site_packages_path)
     ...     finally:
     ...         shutil.rmtree(tmp)
-    >>> print call_py(
+    >>> print_(call_py(
     ...     py_path,
-    ...     "import tellmy.version; print tellmy.version.__version__")
+    ...     "import tellmy.version; print(tellmy.version.__version__)"
+    ...     ))
     1.0
-    <BLANKLINE>
+
     >>> write('buildout.cfg',
     ... '''
     ... [buildout]
@@ -2058,11 +2053,10 @@
 the comment leading up to zc.buildout.easy_install._easy_install_cmd).
 Now the install works correctly, as seen here.
 
-    >>> print system(buildout)
+    >>> run(buildout)
     Installing eggs.
     Getting distribution for 'tellmy.version==1.1'.
     Got tellmy.version 1.1.
-    <BLANKLINE>
 
     """
 
@@ -2233,26 +2227,22 @@
     >>> zc.buildout.easy_install.clear_index_cache()
     >>> rmdir(example_dest)
     >>> example_dest = tmpdir('site-packages-example-install')
-    >>> workingset = zc.buildout.easy_install.install(
+    >>> print(raises('MissingDistribution', zc.buildout.easy_install.install,
     ...     ['demoneeded'], example_dest, links=[], executable=py_path,
     ...     index=None,
-    ...     allowed_eggs_from_site_packages=['demo'])
-    Traceback (most recent call last):
-        ...
-    MissingDistribution: Couldn't find a distribution for 'demoneeded'.
+    ...     allowed_eggs_from_site_packages=['demo']))
+    Couldn't find a distribution for 'demoneeded'.
 
 Here's the same, but with an empty list.
 
     >>> zc.buildout.easy_install.clear_index_cache()
     >>> rmdir(example_dest)
     >>> example_dest = tmpdir('site-packages-example-install')
-    >>> workingset = zc.buildout.easy_install.install(
+    >>> print(raises('MissingDistribution', zc.buildout.easy_install.install,
     ...     ['demoneeded'], example_dest, links=[], executable=py_path,
     ...     index=None,
-    ...     allowed_eggs_from_site_packages=[])
-    Traceback (most recent call last):
-        ...
-    MissingDistribution: Couldn't find a distribution for 'demoneeded'.
+    ...     allowed_eggs_from_site_packages=[]))
+    Couldn't find a distribution for 'demoneeded'.
 
 Of course, this doesn't stop us from getting a package from elsewhere.  Here,
 we add a link server.
@@ -2276,13 +2266,11 @@
     >>> zc.buildout.easy_install.clear_index_cache()
     >>> rmdir(example_dest)
     >>> example_dest = tmpdir('site-packages-example-install')
-    >>> workingset = zc.buildout.easy_install.install(
+    >>> print(raises('MissingDistribution', zc.buildout.easy_install.install,
     ...     ['demoneeded'], example_dest, links=[], executable=py_path,
     ...     index=None, include_site_packages=False,
-    ...     allowed_eggs_from_site_packages=['demoneeded'])
-    Traceback (most recent call last):
-        ...
-    MissingDistribution: Couldn't find a distribution for 'demoneeded'.
+    ...     allowed_eggs_from_site_packages=['demoneeded']))
+    Couldn't find a distribution for 'demoneeded'.
 
     """
 
@@ -2347,7 +2335,7 @@
 site-packages are at the end.  They were not before this bugfix.
 
     >>> test = 'import pprint, sys; pprint.pprint(sys.path[-4:])'
-    >>> print call_py(join(interpreter_bin_dir, 'py'), test)
+    >>> print(call_py(join(interpreter_bin_dir, 'py'), test))
     ['/interpreter/eggs/other-1.0-pyN.N.egg',
      '/interpreter/eggs/demoneeded-1.1-pyN.N.egg',
      '/executable_buildout/eggs/setuptools-0.0-pyN.N.egg',
@@ -2380,7 +2368,7 @@
     >>> test = (
     ...     "import subprocess, sys; subprocess.call("
     ...     "[sys.executable, '-c', "
-    ...     "'import eggrecipedemo; print eggrecipedemo.x'])")
+    ...     "'import eggrecipedemo; print(eggrecipedemo.x)'])")
     >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts(
     ...     interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir,
     ...     reqs=['demo'], interpreter='py',
@@ -2388,13 +2376,12 @@
 
 This works for the script.
 
-    >>> print system(join(interpreter_bin_dir, 'demo'))
+    >>> run(join(interpreter_bin_dir, 'demo'))
     3
-    <BLANKLINE>
 
 This also works for the generated interpreter.
 
-    >>> print call_py(join(interpreter_bin_dir, 'py'), test)
+    >>> print(call_py(join(interpreter_bin_dir, 'py'), test))
     3
     <BLANKLINE>
 
@@ -2417,7 +2404,7 @@
 You can also see, actually more easily than in the other example, that we
 have the desired eggs available.
 
-    >>> print system(join(interpreter_bin_dir, 'demo')), # doctest: +ELLIPSIS
+    >>> run(join(interpreter_bin_dir, 'demo')) # doctest: +ELLIPSIS
     ['',
      '/interpreter/parts/interpreter',
      '/sample-buildout/foo',
@@ -2427,7 +2414,7 @@
 
 This also works for the generated interpreter, with identical results.
 
-    >>> print call_py(join(interpreter_bin_dir, 'py'), test),
+    >>> print_(call_py(join(interpreter_bin_dir, 'py'), test))
     ... # doctest: +ELLIPSIS
     ['',
      '/interpreter/parts/interpreter',
@@ -2520,12 +2507,11 @@
 
 Now, it is handled smoothly.
 
-    >>> print system(buildout)
+    >>> run(buildout)
     Develop: '/sample-buildout/recipes'
     Getting distribution for 'demoneeded==1.2c1'.
     Got demoneeded 1.2c1.
     Installing dummy.
-    <BLANKLINE>
 
 Here's the same story with a namespace package, which has some additional
 complications behind the scenes.  First, a recipe, in the "tellmy" namespace.
@@ -2553,12 +2539,12 @@
     ... setup(
     ...     name="tellmy.recipes",
     ...     packages=['tellmy', 'tellmy.recipes'],
-    ...     install_requires=['setuptools'],
+    ...     install_requires=[%(setuptools_key)r],
     ...     namespace_packages=['tellmy'],
     ...     entry_points = {'zc.buildout':
     ...                     ['dummy = tellmy.recipes.dummy:Dummy']},
     ...     )
-    ... ''')
+    ... ''' % globals())
 
 Now, a buildout that uses it.
 
@@ -2581,19 +2567,17 @@
 
 Now we actually run the buildout.
 
-    >>> print system(buildout)
+    >>> run(buildout)
     Develop: '/sample-buildout/ns'
     Develop: '/sample-buildout/recipes'
     Uninstalling dummy.
     Installing dummy.
-    <BLANKLINE>
 
     """
 
 if not zc.buildout.testing.script_in_shebang:
     del bootstrap_makes_buildout_that_works_with_system_python
 
-
 def test_exit_codes():
     """
     >>> import subprocess
@@ -2673,11 +2657,11 @@
     ... import os
     ... class Bad:
     ...     def __init__(self, *_):
-    ...         print os.getcwd()
+    ...         print(os.getcwd())
     ...     def install(self):
-    ...         print os.getcwd()
+    ...         print(os.getcwd())
     ...         os.chdir('bad_start')
-    ...         print os.getcwd()
+    ...         print(os.getcwd())
     ...         return ()
     ... ''')
 
@@ -2700,8 +2684,8 @@
     ... ''')
 
     >>> os.chdir('bad_start')
-    >>> print system(join(sample_buildout, 'bin', 'buildout')
-    ...              +' -c '+join(sample_buildout, 'buildout.cfg')),
+    >>> run(join(sample_buildout, 'bin', 'buildout')
+    ...              +' -c '+join(sample_buildout, 'buildout.cfg'))
     Develop: '/sample-buildout/.'
     /sample-buildout
     /sample-buildout
@@ -2730,7 +2714,7 @@
 
 
     >>> for dist in ws:
-    ...     print dist
+    ...     print(dist)
     demo 0.2
     demoneeded 1.1
 
@@ -2743,7 +2727,7 @@
 def bug_75607_buildout_should_not_run_if_it_creates_an_empty_buildout_cfg():
     """
     >>> remove('buildout.cfg')
-    >>> print system(buildout),
+    >>> run(buildout)
     While:
       Initializing.
     Error: Couldn't open /sample-buildout/buildout.cfg
@@ -2784,7 +2768,7 @@
     ... eggs = pack0
     ... ''')
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/pack0'
     Develop: '/sample-buildout/pack1'
     Develop: '/sample-buildout/pack2'
@@ -2800,7 +2784,7 @@
 
     However, if we run in verbose mode, we can see why packages were included:
 
-    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    >>> run(buildout+' -v') # doctest: +ELLIPSIS
     Installing 'zc.buildout', 'setuptools'.
     We have a develop egg: zc.buildout 1.0.0
     We have the best distribution that satisfies 'setuptools'.
@@ -2865,7 +2849,7 @@
     ...             },
     ...       )
     ... ''')
-    >>> print system(buildout+' setup '+src+' bdist_egg'),
+    >>> run(buildout+' setup '+src+' bdist_egg')
     ... # doctest: +ELLIPSIS
     Running setup ...
     creating 'dist/wackyextension-1-...
@@ -2889,7 +2873,7 @@
 When we run the buildout. it will load the extension from the dist
 directory and then use the wacky extension to load the demo package
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Getting distribution for 'wackyextension'.
     Got wackyextension 1.
     Installing demo.
@@ -2911,7 +2895,7 @@
     ... setup(name='foo')
     ... ''')
 
-    >>> print system(buildout+' setup test bdist_egg'), # doctest: +ELLIPSIS
+    >>> run(buildout+' setup test bdist_egg') # doctest: +ELLIPSIS
     Running setup script 'test/setup.py'.
     ...
 
@@ -2972,9 +2956,9 @@
         )
 
     if dist.extras:
-        print 'downloaded', dist.version
+        print('downloaded', dist.version)
     else:
-        print 'had', dist.version
+        print('had', dist.version)
     sys.path_importer_cache.clear()
 
 def prefer_final():
@@ -3091,7 +3075,7 @@
     ... eggs = demo
     ... ''' % globals())
 
-    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    >>> run(buildout+' -v') # doctest: +ELLIPSIS
     Installing 'zc.buildout', 'setuptools'.
     ...
     Picked: demo = 0.4c1
@@ -3113,7 +3097,7 @@
     ... eggs = demo
     ... ''' % globals())
 
-    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    >>> run(buildout+' -v') # doctest: +ELLIPSIS
     Installing 'zc.buildout', 'setuptools'.
     ...
     Picked: demo = 0.4c1
@@ -3135,7 +3119,7 @@
     ... eggs = demo
     ... ''' % globals())
 
-    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    >>> run(buildout+' -v') # doctest: +ELLIPSIS
     Installing 'zc.buildout', 'setuptools'.
     ...
     Picked: demo = 0.3
@@ -3156,7 +3140,7 @@
     ... eggs = demo
     ... ''' % globals())
 
-    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    >>> run(buildout+' -v') # doctest: +ELLIPSIS
     While:
       Initializing.
     Error: Invalid value for prefer-final option: no
@@ -3190,7 +3174,7 @@
     ... recipe = demorecipe
     ... ''' % globals())
 
-    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    >>> run(buildout+' -v') # doctest: +ELLIPSIS
     Installing ...
     Picked: demoextension = 1.0
     ...
@@ -3214,7 +3198,7 @@
     ... recipe = demorecipe
     ... ''' % globals())
 
-    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    >>> run(buildout+' -v') # doctest: +ELLIPSIS
     Installing ...
     Picked: demoextension = 1.0
     ...
@@ -3236,7 +3220,7 @@
     ... recipe = demorecipe
     ... ''' % globals())
 
-    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    >>> run(buildout+' -v') # doctest: +ELLIPSIS
     Installing ...
     Picked: demoextension = 1.1b1
     ...
@@ -3257,7 +3241,7 @@
     ... recipe = demorecipe
     ... ''' % globals())
 
-    >>> print system(buildout+' -v'), # doctest: +ELLIPSIS
+    >>> run(buildout+' -v') # doctest: +ELLIPSIS
     While:
       Initializing.
     Error: Invalid value for accept-buildout-test-releases option: no
@@ -3287,7 +3271,7 @@
     ... parts =
     ... ''')
 
-    >>> print system(join('bin', 'buildout')),
+    >>> run(join('bin', 'buildout'))
     Develop: '/sample-buildout/foo'
 
     >>> ls('develop-eggs')
@@ -3338,7 +3322,7 @@
     ...         pkg_resources.Requirement.parse('setuptools')).version,
     ...        distribute_version))
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Installing foo.
     Getting distribution for 'foo==1'.
     Got foo 1.
@@ -3366,11 +3350,11 @@
     >>> write('t.py',
     ... '''
     ... import eggrecipedemo, eggrecipedemoneeded
-    ... print eggrecipedemo.main.func_code.co_filename
-    ... print eggrecipedemoneeded.f.func_code.co_filename
+    ... print(eggrecipedemo.main.func_code.co_filename)
+    ... print(eggrecipedemoneeded.f.func_code.co_filename)
     ... ''')
 
-    >>> print system(join('bin', 'py')+ ' t.py'),
+    >>> run(join('bin', 'py')+ ' t.py')
     /sample-buildout/eggs/demo-0.4c1-py2.4.egg/eggrecipedemo.py
     /sample-buildout/eggs/demoneeded-1.2c1-py2.4.egg/eggrecipedemoneeded.py
 
@@ -3393,7 +3377,7 @@
     ... eggs-directory = ${buildout:directory}/develop-eggs
     ... parts =
     ... ''' % globals())
-    >>> print system(buildout),
+    >>> run(buildout)
 
     """
 
@@ -3424,7 +3408,7 @@
 
     We can see that both eggs were found:
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/sampley'
     Develop: '/sample-buildout/samplez'
     Installing eggs.
@@ -3456,7 +3440,7 @@
     We should get one of the eggs, and a warning for the pattern that
     did not match anything.
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Develop: '/sample-buildout/samplea'
     Couldn't develop '/sample-buildout/grumble*' (not found)
     Installing eggs.
@@ -3511,7 +3495,7 @@
     ... <= p1
     ... ''')
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Installing p1.
       foo='1\n2 b'
       recipe='zc.buildout:debug'
@@ -3551,7 +3535,7 @@
     ... x = ${buildout:bar-option} ${buildout:foo-option}
     ... ''')
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Installing p.
       recipe='zc.buildout:debug'
       x='bar\nbaz foo\nham'
@@ -3578,7 +3562,7 @@
     ... <= p1
     ... ''')
 
-    >>> print system(buildout+' buildout:parts+=p2 p1:foo+=bar'),
+    >>> run(buildout+' buildout:parts+=p2 p1:foo+=bar')
     Installing p1.
       foo='1 a\nb\nbar'
       recipe='zc.buildout:debug'
@@ -3596,6 +3580,7 @@
 
 def create_sample_namespace_eggs(dest, site_packages_path=None):
     from zc.buildout.testing import write, mkdir
+    setuptools_key_ = setuptools_key
     for pkg, version in (('version', '1.0'), ('version', '1.1'),
                          ('fortune', '1.0')):
         tmp = tempfile.mkdtemp()
@@ -3616,7 +3601,7 @@
                 " name='tellmy.%(pkg)s',\n"
                 " package_dir = {'': 'src'},\n"
                 " packages = ['tellmy', 'tellmy.%(pkg)s'],\n"
-                " install_requires = ['setuptools'],\n"
+                " install_requires = [%(setuptools_key_)r],\n"
                 " namespace_packages=['tellmy'],\n"
                 " zip_safe=True, version=%(version)r,\n"
                 " author='bob', url='bob', author_email='bob')\n"
@@ -3713,7 +3698,7 @@
         tmp, 'eggrecipedemo.py',
         'import eggrecipedemoneeded\n'
         'x=%s\n'
-        'def main(): print x, eggrecipedemoneeded.y\n'
+        'def main(): print(x, eggrecipedemoneeded.y)\n'
         % minor_version)
     write(
         tmp, 'setup.py',
@@ -3776,7 +3761,7 @@
     finally:
         shutil.rmtree(tmp)
 
-extdemo_c = """
+extdemo_c2 = """
 #include <Python.h>
 #include <extdemo.h>
 
@@ -3795,12 +3780,43 @@
 }
 """
 
+extdemo_c3 = """
+#include <Python.h>
+#include <extdemo.h>
+
+static PyMethodDef methods[] = {{NULL}};
+
+#define MOD_DEF(ob, name, doc, methods) \
+	  static struct PyModuleDef moduledef = { \
+	    PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \
+	  ob = PyModule_Create(&moduledef);
+
+#define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
+
+MOD_INIT(extdemo)
+{
+    PyObject *m;
+
+    MOD_DEF(m, "extdemo", "", methods);
+
+#ifdef TWO
+    PyModule_AddObject(m, "val", PyLong_FromLong(2));
+#else
+    PyModule_AddObject(m, "val", PyLong_FromLong(EXTDEMO));
+#endif
+
+    return m;
+}
+"""
+
+extdemo_c = sys.version_info[0] < 3 and extdemo_c2 or extdemo_c3
+
 extdemo_setup_py = """
 import os
 from distutils.core import setup, Extension
 
 if os.environ.get('test-variable'):
-    print "Have environment test-variable:", os.environ['test-variable']
+    print("Have environment test-variable:", os.environ['test-variable'])
 
 setup(name = "extdemo", version = "%s", url="http://www.zope.org",
       author="Demo", author_email="demo at demo.com",
@@ -3850,15 +3866,19 @@
         zip = zipfile.ZipFile(dest, 'a')
         zip.writestr(
             'EGG-INFO/PKG-INFO',
-            zip.read('EGG-INFO/PKG-INFO').replace("Version: %s" % oldver,
-                                                  "Version: %s" % version)
+            zip.read('EGG-INFO/PKG-INFO').replace(
+                ("Version: %s" % oldver).encode(),
+                ("Version: %s" % version).encode(),
+                )
             )
         zip.close()
     else:
         shutil.copytree(dist.location, dest)
         info_path = os.path.join(dest, 'EGG-INFO', 'PKG-INFO')
-        info = open(info_path).read().replace("Version: %s" % oldver,
-                                              "Version: %s" % version)
+        info = open(info_path).read().replace(
+            ("Version: %s" % oldver),
+            ("Version: %s" % version),
+            )
         open(info_path, 'w').write(info)
 
 def getWorkingSetWithBuildoutEgg(test):
@@ -3880,7 +3900,7 @@
             '-q', 'bdist_egg', '-d', eggs,
             dict(os.environ,
                  PYTHONPATH=pkg_resources.working_set.find(
-                               pkg_resources.Requirement.parse('setuptools')
+                               pkg_resources.Requirement.parse(setuptools_key)
                                ).location,
                  ),
             ) == 0
@@ -3906,12 +3926,8 @@
     makeNewRelease('zc.buildout', ws, new_releases)
     makeNewRelease('zc.buildout', ws, new_releases, '100.0b1')
     os.mkdir(os.path.join(new_releases, 'zc.buildout'))
-    if zc.buildout.easy_install.is_distribute:
-        makeNewRelease('distribute', ws, new_releases)
-        os.mkdir(os.path.join(new_releases, 'distribute'))
-    else:
-        makeNewRelease('setuptools', ws, new_releases)
-        os.mkdir(os.path.join(new_releases, 'setuptools'))
+    makeNewRelease(setuptools_key, ws, new_releases)
+    os.mkdir(os.path.join(new_releases, setuptools_key))
 
 def bootstrapSetup(test):
     easy_install_SetUp(test)
@@ -3987,6 +4003,8 @@
                 (re.compile(r'\S+buildout.py'), 'buildout.py'),
                 (re.compile(r'line \d+'), 'line NNN'),
                 (re.compile(r'py\(\d+\)'), 'py(NNN)'),
+                (re.compile(r'zc.buildout.buildout.MissingOption'),
+                 'MissingOption'),
                 ])
             ),
 
@@ -4016,7 +4034,9 @@
                 (re.compile('distribute'), 'setuptools'),
                 (re.compile("\nUnused options for buildout: "
                             "'(distribute|setuptools)\-version'\."),
-                 '')
+                 ''),
+                (re.compile('subprocess.CalledProcessError'),
+                 'CalledProcessError'),
                 ])
             ),
 

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/testselectingpython.py
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/testselectingpython.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/testselectingpython.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -11,8 +11,10 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
+from zope.testing import renormalizing
+from zc.buildout.easy_install import setuptools_key
+
 import os, re, subprocess, sys, textwrap, unittest, doctest
-from zope.testing import renormalizing
 import zc.buildout.tests
 import zc.buildout.testing
 
@@ -60,12 +62,12 @@
         executable_parts = os.path.join(executable_dir, 'parts')
         test.globs['mkdir'](executable_parts)
         ws = zc.buildout.easy_install.install(
-            ['setuptools'], executable_dir,
+            [setuptools_key], executable_dir,
             index='http://www.python.org/pypi/',
             always_unzip=True, executable=other_executable)
         zc.buildout.easy_install.sitepackage_safe_scripts(
             executable_dir, ws, other_executable, executable_parts,
-            reqs=['setuptools'], interpreter='py')
+            reqs=[setuptools_key], interpreter='py')
         original_executable = other_executable
         other_executable = os.path.join(executable_dir, 'py')
         assert not subprocess.call(

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/update.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/update.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/update.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -44,7 +44,7 @@
     ...     def install(self):
     ...         for project in 'zc.buildout', 'setuptools':
     ...             req = pkg_resources.Requirement.parse(project)
-    ...             print project, pkg_resources.working_set.find(req).version
+    ...             print(project, pkg_resources.working_set.find(req).version)
     ...         return ()
     ...     update = install
     ... """)
@@ -64,7 +64,7 @@
 Now if we run the buildout, the buildout will upgrade itself to the
 new versions found in new releases:
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Getting distribution for 'zc.buildout'.
     Got zc.buildout 99.99.
     Getting distribution for 'setuptools'.
@@ -140,7 +140,7 @@
 
 Now we can see that we actually "upgrade" to an earlier version.
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Upgraded:
       zc.buildout version 1.0.0,
       setuptools version 0.6;
@@ -167,7 +167,7 @@
     ... recipe = showversions
     ... """ % dict(new_releases=new_releases))
 
-    >>> print system(buildout+' -o'),
+    >>> run(buildout+' -o')
     Develop: '/sample-buildout/showversions'
     Updating show-versions.
     zc.buildout 1.0.0
@@ -175,7 +175,7 @@
 
 Or in non-newest mode:
 
-    >>> print system(buildout+' -N'),
+    >>> run(buildout+' -N')
     Develop: '/sample-buildout/showversions'
     Updating show-versions.
     zc.buildout 1.0.0
@@ -195,7 +195,7 @@
     ... """ % dict(new_releases=new_releases))
 
     >>> cd(sample_buildout2)
-    >>> print system(buildout),
+    >>> run(buildout)
     Creating directory '/sample_buildout2/bin'.
     Creating directory '/sample_buildout2/parts'.
     Creating directory '/sample_buildout2/eggs'.
@@ -230,8 +230,7 @@
     ... recipe = showversions
     ... """ % dict(new_releases=new_releases))
 
-    >>> print system(buildout +
-    ...              ' buildout:accept-buildout-test-releases=true'),
+    >>> run(buildout + ' buildout:accept-buildout-test-releases=true')
     ... # doctest: +NORMALIZE_WHITESPACE
     Getting distribution for 'zc.buildout'.
     Got zc.buildout 100.0b1.
@@ -254,12 +253,12 @@
     >>> import sys
     >>> if sys.platform.startswith('win'):
     ...     buildout_script += '-script.py'
-    >>> print open(buildout_script).read() # doctest: +ELLIPSIS
+    >>> print(open(buildout_script).read()) # doctest: +ELLIPSIS
     #...
     sys.argv.insert(1, 'buildout:accept-buildout-test-releases=true')
-    print ('NOTE: Accepting early releases of build system packages.  Rerun '
-           'bootstrap without --accept-buildout-test-releases (-t) to return to '
-           'default behavior.')
+    print('NOTE: Accepting early releases of build system packages.  Rerun '
+          'bootstrap without --accept-buildout-test-releases (-t) to return to '
+          'default behavior.')
     ...
 
 If the update process for buildout or setuptools fails the error should be
@@ -269,8 +268,7 @@
     >>> version = sys.version_info[0:2]
     >>> egg = new_releases + '/zc.buildout-99.99-py%s.%s.egg ' % version
     >>> copy_egg = new_releases + '/zc.buildout-1000-py%s.%s.egg ' % version
-    >>> system('cp ' + egg  + copy_egg)
-    ''
+    >>> run('cp ' + egg  + copy_egg)
 
 Create a broken egg
 

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/upgrading_distribute.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/upgrading_distribute.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/upgrading_distribute.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -50,7 +50,5 @@
     ...     executable=sys.executable,
     ...     always_unzip=True)
     >>> installer._get_dist = mock_get_dist
-    >>> installer._call_easy_install('setuptools', None, dest, dist)
-    Traceback (most recent call last):
-    ...
-    UserError: Couldn't install: nonexisting.tgz
+    >>> print(raises('UserError', installer._call_easy_install, 'setuptools', None, dest, dist))
+    Couldn't install: nonexisting.tgz

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/virtualenv.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/virtualenv.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/virtualenv.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -76,7 +76,7 @@
     ...     py_file.write(line)
     ...     if line.startswith('environ = os.environ.copy()'):
     ...         py_file.write(extra)
-    ...         print 'Rewritten.'
+    ...         print('Rewritten.')
     ...
     Rewritten.
     >>> py_file.close()
@@ -114,14 +114,15 @@
     ...     sys.meta_path.append(ImportHook)
     ... ''' % (py_path,))
     >>> sitecustomize_file.close()
-    >>> print call_py(
+    >>> print(call_py(
     ...     _safe_arg(py_path),
-    ...     "import ConfigParser")
+    ...     "import ConfigParser"))
     <BLANKLINE>
-    >>> print 'X'; print call_py(
+
+    >>> print('X'); print(call_py(
     ...     _safe_arg(py_path),
     ...     "import ConfigParser",
-    ...     '-S') # doctest: +ELLIPSIS
+    ...     '-S')) # doctest: +ELLIPSIS
     X...Traceback (most recent call last):
       ...
     ImportError: No module named ConfigParser
@@ -157,9 +158,9 @@
     ... parts =
     ... ''')
     >>> write('bootstrap.py', open(bootstrap_py).read())
-    >>> print 'X'; print system(
+    >>> print('X'); run(
     ...     _safe_arg(py_path)+' '+
-    ...     'bootstrap.py'); print 'X' # doctest: +ELLIPSIS
+    ...     'bootstrap.py'); print('X') # doctest: +ELLIPSIS
     X...
     Generated script '/broken_S/bin/buildout'.
     ...
@@ -208,7 +209,7 @@
     ... eggs = demo
     ... ''' % globals())
 
-    >>> print system(buildout), # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+    >>> run(buildout) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
     Installing eggs.
     Getting distribution for 'demo'.
     Got demo 0.4c1.
@@ -232,19 +233,19 @@
 you don't want those warnings for those particular recipes that use the
 new features, you can use the "-s" option to squelch the warnings.
 
-    >>> print system(buildout + ' -s'),
+    >>> run(buildout + ' -s')
     Updating eggs.
 
 A lower verbosity (one or more -q options) also quiets the warning.
 
-    >>> print system(buildout + ' -q'),
+    >>> run(buildout + ' -q')
 
 Notice that, as we saw before with bin/buildout, the generated scripts
 are old-style, because the new-style feature gracefully degrades to the
 previous implementation when it encounters an executable with a broken
 dash-S.
 
-    >>> print 'X'; cat('bin', 'py') # doctest: +ELLIPSIS
+    >>> print('X'); cat('bin', 'py') # doctest: +ELLIPSIS
     X...
     <BLANKLINE>
     import sys

Modified: zc.buildout/branches/python-3-2/src/zc/buildout/windows.txt
===================================================================
--- zc.buildout/branches/python-3-2/src/zc/buildout/windows.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/src/zc/buildout/windows.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -21,7 +21,7 @@
     ...              name)
     ...
     ...     def install(self):
-    ...         print "can't remove read only files"
+    ...         print("can't remove read only files")
     ...         if not os.path.exists (self.location):
     ...             os.makedirs (self.location)
     ...
@@ -43,7 +43,7 @@
 
     >>> write('recipe', 'README', '')
 
-    >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS
+    >>> run(buildout+' setup recipe bdist_egg') # doctest: +ELLIPSIS
     Running setup script 'recipe/setup.py'.
     ...
 
@@ -59,7 +59,7 @@
     ... recipe = spam
     ... ''' % join('recipe', 'dist'))
 
-    >>> print system(buildout),
+    >>> run(buildout)
     Getting distribution for 'spam'.
     Got spam 1.
     Installing foo.

Modified: zc.buildout/branches/python-3-2/z3c.recipe.scripts_/src/z3c/recipe/scripts/scripts.py
===================================================================
--- zc.buildout/branches/python-3-2/z3c.recipe.scripts_/src/z3c/recipe/scripts/scripts.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/z3c.recipe.scripts_/src/z3c/recipe/scripts/scripts.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -23,7 +23,7 @@
 
     def __init__(self, buildout, name, options):
         if 'extends' in options:
-            for key, value in buildout[options['extends']].items():
+            for key, value in list(buildout[options['extends']].items()):
                 options.setdefault(key, value)
         super(Base, self).__init__(buildout, name, options)
         self.default_eggs = '' # Disables feature from zc.recipe.egg.

Modified: zc.buildout/branches/python-3-2/z3c.recipe.scripts_/src/z3c/recipe/scripts/tests.py
===================================================================
--- zc.buildout/branches/python-3-2/z3c.recipe.scripts_/src/z3c/recipe/scripts/tests.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/z3c.recipe.scripts_/src/z3c/recipe/scripts/tests.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -230,7 +230,7 @@
 Let's look at the site.py that was generated:
 
     >>> import sys
-    >>> sys.stdout.write('#'); cat(sample_buildout, 'parts', 'py', 'site.py')
+    >>> print_('#'); cat(sample_buildout, 'parts', 'py', 'site.py')
     ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
     #...
     def addsitepackages(known_paths):

Modified: zc.buildout/branches/python-3-2/zc.recipe.egg_/src/zc/recipe/egg/custom.py
===================================================================
--- zc.buildout/branches/python-3-2/zc.recipe.egg_/src/zc/recipe/egg/custom.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/zc.recipe.egg_/src/zc/recipe/egg/custom.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -62,7 +62,7 @@
             self.environment = buildout[environment_section]
         else:
             self.environment = {}
-        environment_data = self.environment.items()
+        environment_data = list(self.environment.items())
         environment_data.sort()
         options['_environment-data'] = repr(environment_data)
 
@@ -101,7 +101,7 @@
 
     def _set_environment(self):
         self._saved_environment = {}
-        for key, value in self.environment.items():
+        for key, value in list(self.environment.items()):
             if key in os.environ:
                 self._saved_environment[key] = os.environ[key]
             # Interpolate value with variables from environment. Maybe there

Modified: zc.buildout/branches/python-3-2/zc.recipe.egg_/src/zc/recipe/egg/egg.py
===================================================================
--- zc.buildout/branches/python-3-2/zc.recipe.egg_/src/zc/recipe/egg/egg.py	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/zc.recipe.egg_/src/zc/recipe/egg/egg.py	2011-03-17 17:47:39 UTC (rev 121011)
@@ -16,7 +16,7 @@
 $Id$
 """
 
-import UserDict, logging, os, re, zipfile
+import collections, logging, os, re, zipfile
 import zc.buildout
 import zc.buildout.easy_install
 
@@ -198,7 +198,7 @@
 Egg = Scripts
 
 
-class _BackwardsSupportOption(UserDict.UserDict):
+class _BackwardsSupportOption(collections.UserDict):
 
     def __init__(self, data):
         self.data = data # We want to show mutations to the underlying dict.

Modified: zc.buildout/branches/python-3-2/zc.recipe.egg_/src/zc/recipe/egg/selecting-python.txt
===================================================================
--- zc.buildout/branches/python-3-2/zc.recipe.egg_/src/zc/recipe/egg/selecting-python.txt	2011-03-17 17:41:46 UTC (rev 121010)
+++ zc.buildout/branches/python-3-2/zc.recipe.egg_/src/zc/recipe/egg/selecting-python.txt	2011-03-17 17:47:39 UTC (rev 121011)
@@ -131,7 +131,7 @@
             sys.argv[:] = _args
             __file__ = _args[0]
             del _options, _args
-            execfile(__file__)
+            exec(compile(open(__file__).read(), __file__, "exec"))
     <BLANKLINE>
     if _interactive:
         del _interactive



More information about the checkins mailing list