[Checkins] SVN: zc.buildout/branches/regebro-python3/ Almost boostraps for development. (Need to release zope.testing 4.0 for Python 3 next).

Lennart Regebro regebro at gmail.com
Tue Jul 20 12:11:14 EDT 2010


Log message for revision 114878:
  Almost boostraps for development. (Need to release zope.testing 4.0 for Python 3 next).
  

Changed:
  U   zc.buildout/branches/regebro-python3/bootstrap/bootstrap.py
  U   zc.buildout/branches/regebro-python3/dev.py
  U   zc.buildout/branches/regebro-python3/src/zc/buildout/__init__.py
  U   zc.buildout/branches/regebro-python3/src/zc/buildout/buildout.py
  U   zc.buildout/branches/regebro-python3/src/zc/buildout/download.py
  U   zc.buildout/branches/regebro-python3/src/zc/buildout/easy_install.py
  U   zc.buildout/branches/regebro-python3/src/zc/buildout/rmtree.py

-=-
Modified: zc.buildout/branches/regebro-python3/bootstrap/bootstrap.py
===================================================================
--- zc.buildout/branches/regebro-python3/bootstrap/bootstrap.py	2010-07-20 16:08:12 UTC (rev 114877)
+++ zc.buildout/branches/regebro-python3/bootstrap/bootstrap.py	2010-07-20 16:11:13 UTC (rev 114878)
@@ -18,8 +18,12 @@
 use the -c option to specify an alternate configuration file.
 """
 
-import os, shutil, sys, tempfile, urllib2
+import os, shutil, sys, tempfile
 from optparse import OptionParser
+try: # py3K compat hack:
+    from urllib import urlopen
+except ImportError:
+    from urllib.request import urlopen
 
 tmpeggs = tempfile.mkdtemp()
 
@@ -49,6 +53,9 @@
     VERSION = ''
 
 USE_DISTRIBUTE = options.distribute
+if sys.version > '3':
+    USE_DISTRIBUTE = True
+    
 args = args + ['bootstrap']
 
 try:
@@ -59,12 +66,12 @@
 except ImportError:
     ez = {}
     if USE_DISTRIBUTE:
-        exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py'
-                         ).read() in ez
+        exec(urlopen('http://python-distribute.org/distribute_setup.py'
+                     ).read(), ez)
         ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True)
     else:
-        exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
-                             ).read() in ez
+        exec(urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                     ).read(), ez)
         ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
 
     reload(sys.modules['pkg_resources'])

Modified: zc.buildout/branches/regebro-python3/dev.py
===================================================================
--- zc.buildout/branches/regebro-python3/dev.py	2010-07-20 16:08:12 UTC (rev 114877)
+++ zc.buildout/branches/regebro-python3/dev.py	2010-07-20 16:11:13 UTC (rev 114878)
@@ -19,8 +19,12 @@
 $Id$
 """
 
-import os, shutil, sys, subprocess, urllib2
+import os, shutil, sys, subprocess
 from optparse import OptionParser
+try: # py3K import hack:
+    from urllib import urlopen
+except ImportError:
+    from urllib.request import urlopen
 
 if sys.platform == 'win32':
     def quote(c):
@@ -36,10 +40,10 @@
 # particular because Python 2.6's distutils imports site, so starting
 # with the -S flag is not sufficient.  However, we'll start with that:
 if 'site' in sys.modules:
-    # We will restart with python -S.
     args = sys.argv[:]
     args[0:0] = [sys.executable, '-S']
-    args = map(quote, args)
+    # py3k hack: In python 3 map returns a generator.
+    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
@@ -79,7 +83,7 @@
 if args:
     parser.error('This script accepts no arguments other than its options.')
 
-if options.use_distribute:
+if options.use_distribute or sys.version > '3':
     setup_source = distribute_source
 else:
     setup_source = setuptools_source
@@ -98,9 +102,11 @@
         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')
+    # py3k: urlopen returns bytes in Python3, encode to string:
+    ez_code = urlopen(setup_source).read().decode('latin-1').replace('\r\n', '\n')
     ez = {}
-    exec ez_code in ez
+    # Py3K compat hack:
+    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/regebro-python3/src/zc/buildout/__init__.py
===================================================================
--- zc.buildout/branches/regebro-python3/src/zc/buildout/__init__.py	2010-07-20 16:08:12 UTC (rev 114877)
+++ zc.buildout/branches/regebro-python3/src/zc/buildout/__init__.py	2010-07-20 16:11:13 UTC (rev 114878)
@@ -21,4 +21,5 @@
     """
 
     def __str__(self):
-        return " ".join(map(str, self))
+        # py3 exceptions arenot iterable, use args instead:
+        return " ".join(map(str, self.args))

Modified: zc.buildout/branches/regebro-python3/src/zc/buildout/buildout.py
===================================================================
--- zc.buildout/branches/regebro-python3/src/zc/buildout/buildout.py	2010-07-20 16:08:12 UTC (rev 114877)
+++ zc.buildout/branches/regebro-python3/src/zc/buildout/buildout.py	2010-07-20 16:11:13 UTC (rev 114878)
@@ -14,14 +14,22 @@
 """Buildout main script
 """
 
-from rmtree import rmtree
+
+from zc.buildout.rmtree import rmtree
 try:
     from hashlib import md5
 except ImportError:
     # Python 2.4 and older
     from md5 import md5
 
-import ConfigParser
+try:
+    from ConfigParser import RawConfigParser
+    from UserDict import DictMixin
+except ImportError: # py3
+    from configparser import RawConfigParser
+    from collections import MutableMapping as DictMixin
+    
+import base64
 import copy
 import distutils.errors
 import glob
@@ -33,7 +41,6 @@
 import shutil
 import sys
 import tempfile
-import UserDict
 import zc.buildout
 import zc.buildout.download
 import zc.buildout.easy_install
@@ -76,18 +83,19 @@
 def _print_annotate(data):
     sections = 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
+        print()
+        print('[%s]' % section)
         keys = 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 == '[+]':
@@ -95,7 +103,7 @@
                 elif note == '[-]':
                     line = '-= '
                 else:
-                    print line, note
+                    print(line, note)
                     line = '   '
     print
 
@@ -135,7 +143,7 @@
     }, 'DEFAULT_VALUE')
 
 
-class Buildout(UserDict.DictMixin):
+class Buildout(DictMixin):
 
     def __init__(self, config_file, cloptions,
                  user_defaults=True, windows_restart=False, command=None):
@@ -153,7 +161,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
@@ -465,11 +473,11 @@
         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
@@ -632,7 +640,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):
             pass
 
         # remove created files and directories
@@ -722,7 +730,7 @@
     def _read_installed_part_options(self):
         old = self['buildout']['installed']
         if old and os.path.isfile(old):
-            parser = ConfigParser.RawConfigParser()
+            parser = RawConfigParser()
             parser.optionxform = lambda s: s
             parser.read(old)
             result = {}
@@ -787,7 +795,9 @@
         f = open(installed, 'w')
         _save_options('buildout', installed_options['buildout'], f)
         for part in installed_options['buildout']['parts'].split():
-            print >>f
+            #print >>f # Won't work under py3, so:
+            f.write(os.linesep)
+            f.write('\n') # Needs to be fixed to add the right line ending
             _save_options(part, installed_options[part], f)
         f.close()
 
@@ -913,7 +923,8 @@
             reqs=['zc.buildout'])
 
         # Restart
-        args = map(zc.buildout.easy_install._safe_arg, sys.argv)
+        # py3 hack: map is a generator in python 3
+        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))
@@ -1042,6 +1053,9 @@
 
     def __iter__(self):
         return iter(self._raw)
+    
+    def __len__(self):
+        raise NotImplementedError('__len__')        
 
 
 def _install_and_load(spec, group, entry, buildout):
@@ -1076,14 +1090,16 @@
         return pkg_resources.load_entry_point(
             req.project_name, group, entry)
 
-    except Exception, v:
+    except Exception:
+        # py3 hack:
+        v = sys.exc_info()[1]
         buildout._logger.log(
             1,
             "Could't load %s entry point %s\nfrom %s:\n%s.",
             group, entry, spec, v)
         raise
 
-class Options(UserDict.DictMixin):
+class Options(DictMixin):
 
     def __init__(self, buildout, section, data):
         self.buildout = buildout
@@ -1251,12 +1267,19 @@
         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):
+        for each in self._raw:
+            yield each
+
+    def __len__(self):
+        return len(self._raw)
+
     def copy(self):
         result = self._raw.copy()
         result.update(self._cooked)
@@ -1327,12 +1350,17 @@
         value = '%(__buildout_space_n__)s' + value[2:]
     if value.endswith('\n\t'):
         value = value[:-2] + '%(__buildout_space_n__)s'
-    print >>f, option, '=', value
+    # py3: print to file has different syntax in Python 3
+    # Also, join must take an iterable, not 3 arguments
+    f.write(' '.join((option, '=', value,)))
+    f.write(os.linesep)
 
 def _save_options(section, options, f):
-    print >>f, '[%s]' % section
+    # py3: print to file has different syntax in Python 3
+    f.write('[%s]' % section)
+    f.write(os.linesep)
     items = options.items()
-    items.sort()
+    items = sorted(items)
     for option, value in items:
         _save_option(option, value, f)
 
@@ -1376,7 +1404,7 @@
 
     result = {}
 
-    parser = ConfigParser.RawConfigParser()
+    parser = RawConfigParser()
     parser.optionxform = lambda s: s
     parser.readfp(fp)
     if is_temp:
@@ -1418,24 +1446,29 @@
 ignore_directories = '.svn', 'CVS'
 def _dir_hash(dir):
     hash = md5()
+    
     for (dirpath, dirnames, filenames) in os.walk(dir):
         dirnames[:] = [n for n in dirnames if n not in ignore_directories]
         filenames[:] = [f for f in filenames
                         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))
+        # py3 hack: Hashes can't be made from unicode, so we encode them:
+        dir_names = ' '.join(dirnames)
+        hash.update(dir_names.encode())
+        file_names = ' '.join(filenames)
+        hash.update(file_names.encode())
         for name in filenames:
-            hash.update(open(os.path.join(dirpath, name)).read())
-    return hash.digest().encode('base64').strip()
+            hash.update(open(os.path.join(dirpath, name), 'rb').read())
+    return base64.b64encode(hash.digest()).strip()
 
 def _dists_sig(dists):
     result = []
     for dist in dists:
         location = dist.location
         if dist.precedence == pkg_resources.DEVELOP_DIST:
-            result.append(dist.project_name + '-' + _dir_hash(location))
+            # py3 hack: b64encode (and therefore _dir_hash) returns binary
+            result.append(dist.project_name + '-' + _dir_hash(location).decode())
         else:
             result.append(os.path.basename(location))
     return result
@@ -1629,7 +1662,8 @@
 
 """
 def _help():
-    print _usage
+    # py3 hack
+    print(_usage)
     sys.exit(0)
 
 def main(args=None):
@@ -1690,7 +1724,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:
@@ -1728,7 +1762,8 @@
             getattr(buildout, command)(args)
         except SystemExit:
             pass
-        except Exception, v:
+        except Exception:
+            v = sys.exc_info()[1]
             _doing()
             exc_info = sys.exc_info()
             import pdb, traceback

Modified: zc.buildout/branches/regebro-python3/src/zc/buildout/download.py
===================================================================
--- zc.buildout/branches/regebro-python3/src/zc/buildout/download.py	2010-07-20 16:08:12 UTC (rev 114877)
+++ zc.buildout/branches/regebro-python3/src/zc/buildout/download.py	2010-07-20 16:11:13 UTC (rev 114878)
@@ -24,13 +24,17 @@
 import re
 import shutil
 import tempfile
-import urllib
-import urlparse
+try:
+    import urllib as urlrequest
+    from urlparse import urlparse
+except ImportError: #py3
+    import urllib.request as urlrequest
+    from urllib.parse import urlparse
 import zc.buildout
 
 
-class URLOpener(urllib.FancyURLopener):
-    http_error_default = urllib.URLopener.http_error_default
+class URLOpener(urlrequest.FancyURLopener):
+    http_error_default = urlrequest.URLopener.http_error_default
 
 
 class ChecksumError(zc.buildout.UserError):
@@ -151,7 +155,7 @@
         """
         if re.match(r"^[A-Za-z]:\\", url):
             url = 'file:' + url
-        parsed_url = urlparse.urlparse(url, 'file')
+        parsed_url = urlparse(url, 'file')
         url_scheme, _, url_path = parsed_url[:3]
         if url_scheme == 'file':
             self.logger.debug('Using local resource %s' % url)
@@ -166,11 +170,11 @@
                 "Couldn't download %r in offline mode." % url)
 
         self.logger.info('Downloading %s' % url)
-        urllib._urlopener = url_opener
+        urlrequest._urlopener = url_opener
         handle, tmp_path = tempfile.mkstemp(prefix='buildout-')
         try:
             try:
-                tmp_path, headers = urllib.urlretrieve(url, tmp_path)
+                tmp_path, headers = urlrequest.urlretrieve(url, tmp_path)
                 if not check_md5sum(tmp_path, md5sum):
                     raise ChecksumError(
                         'MD5 checksum mismatch downloading %r' % url)
@@ -195,7 +199,7 @@
         else:
             if re.match(r"^[A-Za-z]:\\", url):
                 url = 'file:' + url
-            parsed = urlparse.urlparse(url, 'file')
+            parsed = urlparse(url, 'file')
             url_path = parsed[2]
 
             if parsed[0] == 'file':

Modified: zc.buildout/branches/regebro-python3/src/zc/buildout/easy_install.py
===================================================================
--- zc.buildout/branches/regebro-python3/src/zc/buildout/easy_install.py	2010-07-20 16:08:12 UTC (rev 114877)
+++ zc.buildout/branches/regebro-python3/src/zc/buildout/easy_install.py	2010-07-20 16:11:13 UTC (rev 114878)
@@ -98,7 +98,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
@@ -124,7 +124,8 @@
     return (stdlib, site_paths)
 
 def _get_version_info(executable):
-    cmd = [executable, '-Sc', 'import sys; print repr(sys.version_info)']
+    # py3 hack: sys.version_info is not a tuple anymore, force it to be a list
+    cmd = [executable, '-Sc', 'import sys; print(repr(tuple(x for x in sys.version_info)))']
     _proc = subprocess.Popen(
         cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     stdout, stderr = _proc.communicate();
@@ -871,7 +872,9 @@
                 if dist is None:
                     try:
                         dist = best[req.key] = env.best_match(req, ws)
-                    except pkg_resources.VersionConflict, err:
+                    except pkg_resources.VersionConflict:
+                        #py3k hack
+                        err = sys.exc_info()[1]
                         raise VersionConflict(err, ws)
                     if dist is None:
                         if destination:
@@ -1097,12 +1100,13 @@
         undo.append(lambda: os.remove(tsetup))
         undo.append(lambda: os.close(fd))
 
-        os.write(fd, runsetup_template % dict(
+        template = runsetup_template % dict(
             setuptools=setuptools_loc,
             setupdir=directory,
             setup=setup,
             __file__ = setup,
-            ))
+        )
+        os.write(fd, template.encode()) #py3 hack: Convert to binary
 
         tmp3 = tempfile.mkdtemp('build', dir=dest)
         undo.append(lambda : shutil.rmtree(tmp3))
@@ -1377,7 +1381,7 @@
     if changed:
         open(script_name, 'w').write(contents)
         try:
-            os.chmod(script_name, 0755)
+            os.chmod(script_name, 493) #py3k hack: 493 == 0755
         except (AttributeError, os.error):
             pass
         logger.info("Generated %s %r.", logged_type, full_name)
@@ -1473,7 +1477,7 @@
         sys.argv[:] = _args
         __file__ = _args[0]
         del _options, _args
-        execfile(__file__)
+        exec(open(__file__).read())
 
 if _interactive:
     del _interactive
@@ -1491,8 +1495,8 @@
     cmd = [executable, "-Sc",
            "import imp; "
            "fp, path, desc = imp.find_module(%r); "
-           "fp.close; "
-           "print path" % (name,)]
+           "fp.close(); "
+           "print(path)" % (name,)] #py3k hack, print()
     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
@@ -1507,7 +1511,8 @@
             'Could not find file for module %s:\n%s', name, stderr)
         return None
     # else: ...
-    res = stdout.strip()
+    #py3k hack, in python 3 you get binary back, so encode to string
+    res = stdout.decode().strip()
     if res.endswith('.pyc') or res.endswith('.pyo'):
         raise RuntimeError('Cannot find uncompiled version of %s' % (name,))
     if not os.path.exists(res):
@@ -1577,6 +1582,7 @@
     addsitepackages_marker = 'def addsitepackages('
     enableusersite_marker = 'ENABLE_USER_SITE = '
     successful_rewrite = False
+
     real_site_path = _get_module_file(executable, 'site')
     real_site = open(real_site_path, 'r')
     site = open(site_path, 'w')
@@ -1719,7 +1725,7 @@
 
 os.chdir(%(setupdir)r)
 sys.argv[0] = %(setup)r
-execfile(%(setup)r)
+exec(open(%(setup)r).read())
 """
 
 

Modified: zc.buildout/branches/regebro-python3/src/zc/buildout/rmtree.py
===================================================================
--- zc.buildout/branches/regebro-python3/src/zc/buildout/rmtree.py	2010-07-20 16:08:12 UTC (rev 114877)
+++ zc.buildout/branches/regebro-python3/src/zc/buildout/rmtree.py	2010-07-20 16:11:13 UTC (rev 114878)
@@ -38,11 +38,11 @@
     Now create a file ...
 
     >>> foo = os.path.join (d, 'foo')
-    >>> open (foo, 'w').write ('huhu')
+    >>> dummy = open (foo, 'w').write ('huhu') #py3hack: write returns byte count in Python 3
 
     and make it unwriteable
 
-    >>> os.chmod (foo, 0400)
+    >>> os.chmod (foo, 256) #py3 hack: 256 = 0400
 
     rmtree should be able to remove it:
 
@@ -54,7 +54,7 @@
     0
     """
     def retry_writeable (func, path, exc):
-        os.chmod (path, 0600)
+        os.chmod (path, 384) # py3 hack: 384 = 0600
         func (path)
 
     shutil.rmtree (path, onerror = retry_writeable)



More information about the checkins mailing list