[Python-checkins] cpython (2.7): Issue #14018: Backport OS X installer updates from 3.3.

ned.deily python-checkins at python.org
Tue Jan 29 09:19:53 CET 2013


http://hg.python.org/cpython/rev/c2830debb15a
changeset:   81799:c2830debb15a
branch:      2.7
user:        Ned Deily <nad at acm.org>
date:        Tue Jan 29 00:07:46 2013 -0800
summary:
  Issue #14018: Backport OS X installer updates from 3.3.

files:
  Mac/BuildScript/README.txt                       |   88 +-
  Mac/BuildScript/build-installer.py               |  504 ++++++---
  Mac/BuildScript/ncurses-5.5.patch                |   36 -
  Mac/BuildScript/resources/ReadMe.txt             |   30 +-
  Mac/BuildScript/scripts/postflight.documentation |    9 -
  Mac/BuildScript/scripts/postflight.framework     |   14 +-
  Mac/Makefile.in                                  |    4 +-
  7 files changed, 408 insertions(+), 277 deletions(-)


diff --git a/Mac/BuildScript/README.txt b/Mac/BuildScript/README.txt
--- a/Mac/BuildScript/README.txt
+++ b/Mac/BuildScript/README.txt
@@ -8,70 +8,84 @@
 an Installer package from the installation plus other files in ``resources`` 
 and ``scripts`` and placed that on a ``.dmg`` disk image.
 
-As of Python 2.7.x and 3.2, PSF practice is to build two installer variants
-for each release:
+For Python 2.7.x and 3.2.x, PSF practice is to build two installer variants
+for each release.
 
 1.  32-bit-only, i386 and PPC universal, capable on running on all machines
-    supported by Mac OS X 10.3.9 through (at least) 10.6::
+    supported by Mac OS X 10.3.9 through (at least) 10.8::
 
-        python build-installer.py \
+        /usr/bin/python build-installer.py \
             --sdk-path=/Developer/SDKs/MacOSX10.4u.sdk \
             --universal-archs=32-bit \
             --dep-target=10.3 
-            # These are the current default options
 
     - builds the following third-party libraries
 
         * Bzip2
+        * NCurses
+        * GNU Readline (GPL)
+        * SQLite 3.7.13
         * Zlib 1.2.3
-        * GNU Readline (GPL)
-        * SQLite 3
-        * NCurses
         * Oracle Sleepycat DB 4.8 (Python 2.x only)
 
     - requires ActiveState ``Tcl/Tk 8.4`` (currently 8.4.19) to be installed for building
 
-    - current target build environment:
+    - recommended build environment:
         
         * Mac OS X 10.5.8 PPC or Intel
-        * Xcode 3.1.4 (or later)
+        * Xcode 3.1.4
         * ``MacOSX10.4u`` SDK (later SDKs do not support PPC G3 processors)
         * ``MACOSX_DEPLOYMENT_TARGET=10.3``
         * Apple ``gcc-4.0``
-        * Python 2.n (n >= 4) for documentation build with Sphinx
+        * system Python 2.5 for documentation build with Sphinx
 
     - alternate build environments:
 
-        * Mac OS X 10.4.11 with Xcode 2.5
-        * Mac OS X 10.6.6 with Xcode 3.2.5
+        * Mac OS X 10.6.8 with Xcode 3.2.6
             - need to change ``/System/Library/Frameworks/{Tcl,Tk}.framework/Version/Current`` to ``8.4``
+        * Note Xcode 4.* does not support building for PPC so cannot be used for this build
+
 
 2.  64-bit / 32-bit, x86_64 and i386 universal, for OS X 10.6 (and later)::
 
-        python build-installer.py \
+        /usr/bin/python build-installer.py \
             --sdk-path=/Developer/SDKs/MacOSX10.6.sdk \
             --universal-archs=intel \
             --dep-target=10.6
 
+    - builds the following third-party libraries
+
+        * NCurses 5.9 (http://bugs.python.org/issue15037)
+        * SQLite 3.7.13
+
     - uses system-supplied versions of third-party libraries
-    
+
         * readline module links with Apple BSD editline (libedit)
         * builds Oracle Sleepycat DB 4.8 (Python 2.x only)
 
     - requires ActiveState Tcl/Tk 8.5.9 (or later) to be installed for building
 
-    - current target build environment:
-        
-        * Mac OS X 10.6.6 (or later)
-        * Xcode 3.2.5 (or later)
+    - recommended build environment:
+
+        * Mac OS X 10.6.8 (or later)
+        * Xcode 3.2.6
         * ``MacOSX10.6`` SDK
         * ``MACOSX_DEPLOYMENT_TARGET=10.6``
         * Apple ``gcc-4.2``
-        * Python 2.n (n >= 4) for documentation build with Sphinx
+        * system Python 2.6 for documentation build with Sphinx
 
     - alternate build environments:
 
-        * none
+        * none.  Xcode 4.x currently supplies two C compilers.
+          ``llvm-gcc-4.2.1`` has been found to miscompile Python 3.3.x and
+          produce a non-functional Python executable.  As it appears to be
+          considered a migration aid by Apple and is not likely to be fixed,
+          its use should be avoided.  The other compiler, ``clang``, has been
+          undergoing rapid development.  While it appears to have become
+          production-ready in the most recent Xcode 4 releases (Xcode 4.5.x
+          as of this writing), there are still some open issues when
+          building Python and there has not yet been the level of exposure in
+          production environments that the Xcode 3 gcc-4.2 compiler has had.
 
 
 General Prerequisites
@@ -87,6 +101,11 @@
 * It is safest to start each variant build with an empty source directory
   populated with a fresh copy of the untarred source.
 
+* It is recommended that you remove any existing installed version of the
+  Python being built::
+
+      sudo rm -rf /Library/Frameworks/Python.framework/Versions/n.n
+
 
 The Recipe
 ----------
@@ -107,9 +126,9 @@
 ...................................
 
 It is also possible to build a 4-way universal installer that runs on 
-OS X Leopard or later::
+OS X 10.5 Leopard or later::
 
-  python 2.6 /build-installer.py \
+    /usr/bin/python /build-installer.py \
         --dep-target=10.5
         --universal-archs=all
         --sdk-path=/Developer/SDKs/MacOSX10.5.sdk
@@ -120,7 +139,8 @@
 variants can only be run on G5 machines running 10.5.  Note that,
 while OS X 10.6 is only supported on Intel-based machines, it is possible
 to run ``ppc`` (32-bit) executables unmodified thanks to the Rosetta ppc
-emulation in OS X 10.5 and 10.6.
+emulation in OS X 10.5 and 10.6.  The 4-way installer variant must be
+built with Xcode 3.  It is not regularly built or tested.
 
 Other ``--universal-archs`` options are ``64-bit`` (``x86_64``, ``ppc64``),
 and ``3-way`` (``ppc``, ``i386``, ``x86_64``).  None of these options
@@ -133,15 +153,21 @@
 Ideally, the resulting binaries should be installed and the test suite run
 on all supported OS X releases and architectures.  As a practical matter,
 that is generally not possible.  At a minimum, variant 1 should be run on
-at least one Intel, one PPC G4, and one PPC G3 system and one each of 
-OS X 10.6, 10.5, 10.4, and 10.3.9.  Not all tests run on 10.3.9.
-Variant 2 should be run on 10.6 in both 32-bit and 64-bit modes.::
+a PPC G4 system with OS X 10.5 and at least one Intel system running OS X
+10.8, 10.7, 10.6, or 10.5.  Variant 2 should be run on 10.8, 10.7, and 10.6
+systems in both 32-bit and 64-bit modes.::
 
-    arch -i386 /usr/local/bin/pythonn.n -m test.regrtest -w -u all 
-    arch -X86_64 /usr/local/bin/pythonn.n -m test.regrtest -w -u all
+    /usr/local/bin/pythonn.n -m test -w -u all,-largefile
+    /usr/local/bin/pythonn.n-32 -m test -w -u all
     
 Certain tests will be skipped and some cause the interpreter to fail
 which will likely generate ``Python quit unexpectedly`` alert messages
-to be generated at several points during a test run.  These can
-be ignored.
+to be generated at several points during a test run.  These are normal
+during testing and can be ignored.
 
+It is also recommend to launch IDLE and verify that it is at least
+functional.  Double-click on the IDLE app icon in ``/Applications/Pythonn.n``.
+It should also be tested from the command line::
+
+    /usr/local/bin/idlen.n
+
diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py
--- a/Mac/BuildScript/build-installer.py
+++ b/Mac/BuildScript/build-installer.py
@@ -1,7 +1,7 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 """
 This script is used to build "official" universal installers on Mac OS X.
-It requires at least Mac OS X 10.4, Xcode 2.2 and the 10.4u SDK for
+It requires at least Mac OS X 10.5, Xcode 3, and the 10.4u SDK for
 32-bit builds.  64-bit or four-way universal builds require at least
 OS X 10.5 and the 10.5 SDK.
 
@@ -10,18 +10,41 @@
 which is used to build the documentation, currently requires at least
 Python 2.4.
 
+In addition to what is supplied with OS X 10.5+ and Xcode 3+, the script
+requires an installed version of hg and a third-party version of
+Tcl/Tk 8.4 (for OS X 10.4 and 10.5 deployment targets) or Tcl/TK 8.5
+(for 10.6 or later) installed in /Library/Frameworks.  When installed,
+the Python built by this script will attempt to dynamically link first to
+Tcl and Tk frameworks in /Library/Frameworks if available otherwise fall
+back to the ones in /System/Library/Framework.  For the build, we recommend
+installing the most recent ActiveTcl 8.4 or 8.5 version.
+
+32-bit-only installer builds are still possible on OS X 10.4 with Xcode 2.5
+and the installation of additional components, such as a newer Python
+(2.5 is needed for Python parser updates), hg, and svn (for the documentation
+build).
+
 Usage: see USAGE variable in the script.
 """
-import platform, os, sys, getopt, textwrap, shutil, urllib2, stat, time, pwd
-import grp
+import platform, os, sys, getopt, textwrap, shutil, stat, time, pwd, grp
+try:
+    import urllib2 as urllib_request
+except ImportError:
+    import urllib.request as urllib_request
+
+STAT_0o755 = ( stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
+             | stat.S_IRGRP |                stat.S_IXGRP
+             | stat.S_IROTH |                stat.S_IXOTH )
+
+STAT_0o775 = ( stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
+             | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP
+             | stat.S_IROTH |                stat.S_IXOTH )
 
 INCLUDE_TIMESTAMP = 1
 VERBOSE = 1
 
 from plistlib import Plist
 
-import MacOS
-
 try:
     from plistlib import writePlist
 except ImportError:
@@ -42,20 +65,35 @@
         if ln.startswith(variable):
             value = ln[len(variable):].strip()
             return value[1:-1]
-    raise RuntimeError, "Cannot find variable %s" % variable[:-1]
+    raise RuntimeError("Cannot find variable %s" % variable[:-1])
+
+_cache_getVersion = None
 
 def getVersion():
-    return grepValue(os.path.join(SRCDIR, 'configure'), 'PACKAGE_VERSION')
+    global _cache_getVersion
+    if _cache_getVersion is None:
+        _cache_getVersion = grepValue(
+            os.path.join(SRCDIR, 'configure'), 'PACKAGE_VERSION')
+    return _cache_getVersion
 
 def getVersionTuple():
     return tuple([int(n) for n in getVersion().split('.')])
 
+def getVersionMajorMinor():
+    return tuple([int(n) for n in getVersion().split('.', 2)])
+
+_cache_getFullVersion = None
+
 def getFullVersion():
+    global _cache_getFullVersion
+    if _cache_getFullVersion is not None:
+        return _cache_getFullVersion
     fn = os.path.join(SRCDIR, 'Include', 'patchlevel.h')
     for ln in open(fn):
         if 'PY_VERSION' in ln:
-            return ln.split()[-1][1:-1]
-    raise RuntimeError, "Cannot find full version??"
+            _cache_getFullVersion = ln.split()[-1][1:-1]
+            return _cache_getFullVersion
+    raise RuntimeError("Cannot find full version??")
 
 # The directory we'll use to create the build (will be erased and recreated)
 WORKDIR = "/tmp/_py"
@@ -111,13 +149,15 @@
 DEPTARGET = '10.3'
 
 target_cc_map = {
-        '10.3': 'gcc-4.0',
-        '10.4': 'gcc-4.0',
-        '10.5': 'gcc-4.0',
-        '10.6': 'gcc-4.2',
+        '10.3': ('gcc-4.0', 'g++-4.0'),
+        '10.4': ('gcc-4.0', 'g++-4.0'),
+        '10.5': ('gcc-4.2', 'g++-4.2'),
+        '10.6': ('gcc-4.2', 'g++-4.2'),
+        '10.7': ('clang', 'clang++'),
+        '10.8': ('clang', 'clang++'),
 }
 
-CC = target_cc_map[DEPTARGET]
+CC, CXX = target_cc_map[DEPTARGET]
 
 PYTHON_3 = getVersionTuple() >= (3, 0)
 
@@ -135,6 +175,13 @@
     --universal-archs=x  universal architectures (options: %(UNIVERSALOPTS)r, default: %(UNIVERSALARCHS)r)
 """)% globals()
 
+# Dict of object file names with shared library names to check after building.
+# This is to ensure that we ended up dynamically linking with the shared
+# library paths and versions we expected.  For example:
+#   EXPECTED_SHARED_LIBS['_tkinter.so'] = [
+#                       '/Library/Frameworks/Tcl.framework/Versions/8.5/Tcl',
+#                       '/Library/Frameworks/Tk.framework/Versions/8.5/Tk']
+EXPECTED_SHARED_LIBS = {}
 
 # Instructions for building libraries that are necessary for building a
 # batteries included python.
@@ -143,6 +190,75 @@
 def library_recipes():
     result = []
 
+    LT_10_5 = bool(DEPTARGET < '10.5')
+
+    if getVersionTuple() >= (3, 3):
+        result.extend([
+          dict(
+              name="XZ 5.0.3",
+              url="http://tukaani.org/xz/xz-5.0.3.tar.gz",
+              checksum='fefe52f9ecd521de2a8ce38c21a27574',
+              configure_pre=[
+                    '--disable-dependency-tracking',
+              ]
+              ),
+        ])
+
+    result.extend([
+          dict(
+              name="NCurses 5.9",
+              url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz",
+              checksum='8cb9c412e5f2d96bc6f459aa8c6282a1',
+              configure_pre=[
+                  "--enable-widec",
+                  "--without-cxx",
+                  "--without-cxx-binding",
+                  "--without-ada",
+                  "--without-curses-h",
+                  "--enable-shared",
+                  "--with-shared",
+                  "--without-debug",
+                  "--without-normal",
+                  "--without-tests",
+                  "--without-manpages",
+                  "--datadir=/usr/share",
+                  "--sysconfdir=/etc",
+                  "--sharedstatedir=/usr/com",
+                  "--with-terminfo-dirs=/usr/share/terminfo",
+                  "--with-default-terminfo-dir=/usr/share/terminfo",
+                  "--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib"%(getVersion(),),
+              ],
+              patchscripts=[
+                  ("ftp://invisible-island.net/ncurses//5.9/ncurses-5.9-20120616-patch.sh.bz2",
+                   "f54bf02a349f96a7c4f0d00922f3a0d4"),
+                   ],
+              useLDFlags=False,
+              install='make && make install DESTDIR=%s && cd %s/usr/local/lib && ln -fs ../../../Library/Frameworks/Python.framework/Versions/%s/lib/lib* .'%(
+                  shellQuote(os.path.join(WORKDIR, 'libraries')),
+                  shellQuote(os.path.join(WORKDIR, 'libraries')),
+                  getVersion(),
+                  ),
+          ),
+          dict(
+              name="SQLite 3.7.13",
+              url="http://www.sqlite.org/sqlite-autoconf-3071300.tar.gz",
+              checksum='c97df403e8a3d5b67bb408fcd6aabd8e',
+              extra_cflags=('-Os '
+                            '-DSQLITE_ENABLE_FTS4 '
+                            '-DSQLITE_ENABLE_FTS3_PARENTHESIS '
+                            '-DSQLITE_ENABLE_RTREE '
+                            '-DSQLITE_TCL=0 '
+                 '%s' % ('','-DSQLITE_WITHOUT_ZONEMALLOC ')[LT_10_5]),
+              configure_pre=[
+                  '--enable-threadsafe',
+                  '--enable-shared=no',
+                  '--enable-static=yes',
+                  '--disable-readline',
+                  '--disable-dependency-tracking',
+              ]
+          ),
+        ])
+
     if DEPTARGET < '10.5':
         result.extend([
           dict(
@@ -150,8 +266,8 @@
               url="http://bzip.org/1.0.6/bzip2-1.0.6.tar.gz",
               checksum='00b516f4704d4a7cb50a1d97e6e8e15b',
               configure=None,
-              install='make install CC=%s PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
-                  CC,
+              install='make install CC=%s CXX=%s, PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
+                  CC, CXX,
                   shellQuote(os.path.join(WORKDIR, 'libraries')),
                   ' -arch '.join(ARCHLIST),
                   SDKPATH,
@@ -162,8 +278,8 @@
               url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz",
               checksum='debc62758716a169df9f62e6ab2bc634',
               configure=None,
-              install='make install CC=%s prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
-                  CC,
+              install='make install CC=%s CXX=%s, prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
+                  CC, CXX,
                   shellQuote(os.path.join(WORKDIR, 'libraries')),
                   ' -arch '.join(ARCHLIST),
                   SDKPATH,
@@ -178,58 +294,12 @@
               patches=[
                   # The readline maintainers don't do actual micro releases, but
                   # just ship a set of patches.
-                  'http://ftp.gnu.org/pub/gnu/readline/readline-6.1-patches/readline61-001',
-                  'http://ftp.gnu.org/pub/gnu/readline/readline-6.1-patches/readline61-002',
+                  ('http://ftp.gnu.org/pub/gnu/readline/readline-6.1-patches/readline61-001',
+                   'c642f2e84d820884b0bf9fd176bc6c3f'),
+                  ('http://ftp.gnu.org/pub/gnu/readline/readline-6.1-patches/readline61-002',
+                   '1a76781a1ea734e831588285db7ec9b1'),
               ]
           ),
-          dict(
-              name="SQLite 3.7.4",
-              url="http://www.sqlite.org/sqlite-autoconf-3070400.tar.gz",
-              checksum='8f0c690bfb33c3cbbc2471c3d9ba0158',
-              configure_env=('CFLAGS="-Os'
-                                  ' -DSQLITE_ENABLE_FTS3'
-                                  ' -DSQLITE_ENABLE_FTS3_PARENTHESIS'
-                                  ' -DSQLITE_ENABLE_RTREE'
-                                  ' -DSQLITE_TCL=0'
-                                  '"'),
-              configure_pre=[
-                  '--enable-threadsafe',
-                  '--enable-shared=no',
-                  '--enable-static=yes',
-                  '--disable-readline',
-                  '--disable-dependency-tracking',
-              ]
-          ),
-          dict(
-              name="NCurses 5.5",
-              url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz",
-              checksum='e73c1ac10b4bfc46db43b2ddfd6244ef',
-              configure_pre=[
-                  "--enable-widec",
-                  "--without-cxx",
-                  "--without-ada",
-                  "--without-progs",
-                  "--without-curses-h",
-                  "--enable-shared",
-                  "--with-shared",
-                  "--datadir=/usr/share",
-                  "--sysconfdir=/etc",
-                  "--sharedstatedir=/usr/com",
-                  "--with-terminfo-dirs=/usr/share/terminfo",
-                  "--with-default-terminfo-dir=/usr/share/terminfo",
-                  "--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib"%(getVersion(),),
-                  "--enable-termcap",
-              ],
-              patches=[
-                  "ncurses-5.5.patch",
-              ],
-              useLDFlags=False,
-              install='make && make install DESTDIR=%s && cd %s/usr/local/lib && ln -fs ../../../Library/Frameworks/Python.framework/Versions/%s/lib/lib* .'%(
-                  shellQuote(os.path.join(WORKDIR, 'libraries')),
-                  shellQuote(os.path.join(WORKDIR, 'libraries')),
-                  getVersion(),
-                  ),
-          ),
         ])
 
     if not PYTHON_3:
@@ -298,9 +368,7 @@
             source="/pydocs",
             readme="""\
                 This package installs the python documentation at a location
-                that is useable for pydoc and IDLE. If you have installed Xcode
-                it will also install a link to the documentation in
-                /Developer/Documentation/Python
+                that is useable for pydoc and IDLE.
                 """,
             postflight="scripts/postflight.documentation",
             required=False,
@@ -326,7 +394,7 @@
         ),
     ]
 
-    if DEPTARGET < '10.4':
+    if DEPTARGET < '10.4' and not PYTHON_3:
         result.append(
             dict(
                 name="PythonSystemFixes",
@@ -358,7 +426,7 @@
     """
     Return the contents of the named file
     """
-    return open(fn, 'rb').read()
+    return open(fn, 'r').read()
 
 def runCommand(commandline):
     """
@@ -370,7 +438,7 @@
     xit = fd.close()
     if xit is not None:
         sys.stdout.write(data)
-        raise RuntimeError, "command failed: %s"%(commandline,)
+        raise RuntimeError("command failed: %s"%(commandline,))
 
     if VERBOSE:
         sys.stdout.write(data); sys.stdout.flush()
@@ -381,7 +449,7 @@
     xit = fd.close()
     if xit is not None:
         sys.stdout.write(data)
-        raise RuntimeError, "command failed: %s"%(commandline,)
+        raise RuntimeError("command failed: %s"%(commandline,))
 
     return data
 
@@ -423,39 +491,60 @@
     # Because we only support dynamic load of only one major/minor version of
     # Tcl/Tk, ensure:
     # 1. there are no user-installed frameworks of Tcl/Tk with version
-    #       higher than the Apple-supplied system version
-    # 2. there is a user-installed framework in /Library/Frameworks with the
-    #       same version as the system version.  This allows users to choose
-    #       to install a newer patch level.
+    #       higher than the Apple-supplied system version in
+    #       SDKROOT/System/Library/Frameworks
+    # 2. there is a user-installed framework (usually ActiveTcl) in (or linked
+    #       in) SDKROOT/Library/Frameworks with the same version as the system
+    #       version. This allows users to choose to install a newer patch level.
 
+    frameworks = {}
     for framework in ['Tcl', 'Tk']:
-        #fw = dict(lower=framework.lower(),
-        #            upper=framework.upper(),
-        #            cap=framework.capitalize())
-        #fwpth = "Library/Frameworks/%(cap)s.framework/%(lower)sConfig.sh" % fw
-        fwpth = 'Library/Frameworks/Tcl.framework/Versions/Current'
+        fwpth = 'Library/Frameworks/%s.framework/Versions/Current' % framework
         sysfw = os.path.join(SDKPATH, 'System', fwpth)
-        libfw = os.path.join('/', fwpth)
+        libfw = os.path.join(SDKPATH, fwpth)
         usrfw = os.path.join(os.getenv('HOME'), fwpth)
-        #version = "%(upper)s_VERSION" % fw
+        frameworks[framework] = os.readlink(sysfw)
+        if not os.path.exists(libfw):
+            fatal("Please install a link to a current %s %s as %s so "
+                    "the user can override the system framework."
+                    % (framework, frameworks[framework], libfw))
         if os.readlink(libfw) != os.readlink(sysfw):
             fatal("Version of %s must match %s" % (libfw, sysfw) )
         if os.path.exists(usrfw):
             fatal("Please rename %s to avoid possible dynamic load issues."
                     % usrfw)
 
+    if frameworks['Tcl'] != frameworks['Tk']:
+        fatal("The Tcl and Tk frameworks are not the same version.")
+
+    # add files to check after build
+    EXPECTED_SHARED_LIBS['_tkinter.so'] = [
+            "/Library/Frameworks/Tcl.framework/Versions/%s/Tcl"
+                % frameworks['Tcl'],
+            "/Library/Frameworks/Tk.framework/Versions/%s/Tk"
+                % frameworks['Tk'],
+            ]
+
     # Remove inherited environment variables which might influence build
     environ_var_prefixes = ['CPATH', 'C_INCLUDE_', 'DYLD_', 'LANG', 'LC_',
                             'LD_', 'LIBRARY_', 'PATH', 'PYTHON']
     for ev in list(os.environ):
         for prefix in environ_var_prefixes:
             if ev.startswith(prefix) :
-                print "INFO: deleting environment variable %s=%s" % (
-                                                    ev, os.environ[ev])
+                print("INFO: deleting environment variable %s=%s" % (
+                                                    ev, os.environ[ev]))
                 del os.environ[ev]
 
-    os.environ['PATH'] = '/bin:/sbin:/usr/bin:/usr/sbin'
-    print "Setting default PATH: %s"%(os.environ['PATH'])
+    base_path = '/bin:/sbin:/usr/bin:/usr/sbin'
+    if 'SDK_TOOLS_BIN' in os.environ:
+        base_path = os.environ['SDK_TOOLS_BIN'] + ':' + base_path
+    # Xcode 2.5 on OS X 10.4 does not include SetFile in its usr/bin;
+    # add its fixed location here if it exists
+    OLD_DEVELOPER_TOOLS = '/Developer/Tools'
+    if os.path.isdir(OLD_DEVELOPER_TOOLS):
+        base_path = base_path + ':' + OLD_DEVELOPER_TOOLS
+    os.environ['PATH'] = base_path
+    print("Setting default PATH: %s"%(os.environ['PATH']))
 
 
 def parseOptions(args=None):
@@ -463,7 +552,7 @@
     Parse arguments and update global settings.
     """
     global WORKDIR, DEPSRC, SDKPATH, SRCDIR, DEPTARGET
-    global UNIVERSALOPTS, UNIVERSALARCHS, ARCHLIST, CC
+    global UNIVERSALOPTS, UNIVERSALARCHS, ARCHLIST, CC, CXX
 
     if args is None:
         args = sys.argv[1:]
@@ -472,18 +561,18 @@
         options, args = getopt.getopt(args, '?hb',
                 [ 'build-dir=', 'third-party=', 'sdk-path=' , 'src-dir=',
                   'dep-target=', 'universal-archs=', 'help' ])
-    except getopt.error, msg:
-        print msg
+    except getopt.GetoptError:
+        print(sys.exc_info()[1])
         sys.exit(1)
 
     if args:
-        print "Additional arguments"
+        print("Additional arguments")
         sys.exit(1)
 
     deptarget = None
     for k, v in options:
         if k in ('-h', '-?', '--help'):
-            print USAGE
+            print(USAGE)
             sys.exit(0)
 
         elif k in ('-d', '--build-dir'):
@@ -511,27 +600,28 @@
                     # target
                     DEPTARGET = default_target_map.get(v, '10.3')
             else:
-                raise NotImplementedError, v
+                raise NotImplementedError(v)
 
         else:
-            raise NotImplementedError, k
+            raise NotImplementedError(k)
 
     SRCDIR=os.path.abspath(SRCDIR)
     WORKDIR=os.path.abspath(WORKDIR)
     SDKPATH=os.path.abspath(SDKPATH)
     DEPSRC=os.path.abspath(DEPSRC)
 
-    CC=target_cc_map[DEPTARGET]
+    CC, CXX=target_cc_map[DEPTARGET]
 
-    print "Settings:"
-    print " * Source directory:", SRCDIR
-    print " * Build directory: ", WORKDIR
-    print " * SDK location:    ", SDKPATH
-    print " * Third-party source:", DEPSRC
-    print " * Deployment target:", DEPTARGET
-    print " * Universal architectures:", ARCHLIST
-    print " * C compiler:", CC
-    print ""
+    print("Settings:")
+    print(" * Source directory:", SRCDIR)
+    print(" * Build directory: ", WORKDIR)
+    print(" * SDK location:    ", SDKPATH)
+    print(" * Third-party source:", DEPSRC)
+    print(" * Deployment target:", DEPTARGET)
+    print(" * Universal architectures:", ARCHLIST)
+    print(" * C compiler:", CC)
+    print(" * C++ compiler:", CXX)
+    print("")
 
 
 
@@ -576,31 +666,18 @@
         xit = fp.close()
         if xit is not None:
             sys.stdout.write(data)
-            raise RuntimeError, "Cannot extract %s"%(archiveName,)
+            raise RuntimeError("Cannot extract %s"%(archiveName,))
 
         return os.path.join(builddir, retval)
 
     finally:
         os.chdir(curdir)
 
-KNOWNSIZES = {
-    "http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz": 7952742,
-    "http://downloads.sleepycat.com/db-4.4.20.tar.gz": 2030276,
-}
-
 def downloadURL(url, fname):
     """
     Download the contents of the url into the file.
     """
-    try:
-        size = os.path.getsize(fname)
-    except OSError:
-        pass
-    else:
-        if KNOWNSIZES.get(url) == size:
-            print "Using existing file for", url
-            return
-    fpIn = urllib2.urlopen(url)
+    fpIn = urllib_request.urlopen(url)
     fpOut = open(fname, 'wb')
     block = fpIn.read(10240)
     try:
@@ -615,6 +692,24 @@
         except:
             pass
 
+def verifyThirdPartyFile(url, checksum, fname):
+    """
+    Download file from url to filename fname if it does not already exist.
+    Abort if file contents does not match supplied md5 checksum.
+    """
+    name = os.path.basename(fname)
+    if os.path.exists(fname):
+        print("Using local copy of %s"%(name,))
+    else:
+        print("Did not find local copy of %s"%(name,))
+        print("Downloading %s"%(name,))
+        downloadURL(url, fname)
+        print("Archive for %s stored as %s"%(name, fname))
+    if os.system(
+            'MD5=$(openssl md5 %s) ; test "${MD5##*= }" = "%s"'
+                % (shellQuote(fname), checksum) ):
+        fatal('MD5 checksum mismatch for file %s' % fname)
+
 def buildRecipe(recipe, basedir, archList):
     """
     Build software using a recipe. This function does the
@@ -635,17 +730,8 @@
     if not os.path.exists(DEPSRC):
         os.mkdir(DEPSRC)
 
-
-    if os.path.exists(sourceArchive):
-        print "Using local copy of %s"%(name,)
-
-    else:
-        print "Did not find local copy of %s"%(name,)
-        print "Downloading %s"%(name,)
-        downloadURL(url, sourceArchive)
-        print "Archive for %s stored as %s"%(name, sourceArchive)
-
-    print "Extracting archive for %s"%(name,)
+    verifyThirdPartyFile(url, recipe['checksum'], sourceArchive)
+    print("Extracting archive for %s"%(name,))
     buildDir=os.path.join(WORKDIR, '_bld')
     if not os.path.exists(buildDir):
         os.mkdir(buildDir)
@@ -655,18 +741,31 @@
     if 'buildDir' in recipe:
         os.chdir(recipe['buildDir'])
 
-
-    for fn in recipe.get('patches', ()):
-        if fn.startswith('http://'):
-            # Download the patch before applying it.
-            path = os.path.join(DEPSRC, os.path.basename(fn))
-            downloadURL(fn, path)
-            fn = path
-
-        fn = os.path.join(curdir, fn)
+    for patch in recipe.get('patches', ()):
+        if isinstance(patch, tuple):
+            url, checksum = patch
+            fn = os.path.join(DEPSRC, os.path.basename(url))
+            verifyThirdPartyFile(url, checksum, fn)
+        else:
+            # patch is a file in the source directory
+            fn = os.path.join(curdir, patch)
         runCommand('patch -p%s < %s'%(recipe.get('patchlevel', 1),
             shellQuote(fn),))
 
+    for patchscript in recipe.get('patchscripts', ()):
+        if isinstance(patchscript, tuple):
+            url, checksum = patchscript
+            fn = os.path.join(DEPSRC, os.path.basename(url))
+            verifyThirdPartyFile(url, checksum, fn)
+        else:
+            # patch is a file in the source directory
+            fn = os.path.join(curdir, patchscript)
+        if fn.endswith('.bz2'):
+            runCommand('bunzip2 -fk %s' % shellQuote(fn))
+            fn = fn[:-4]
+        runCommand('sh %s' % shellQuote(fn))
+        os.unlink(fn)
+
     if configure is not None:
         configure_args = [
             "--prefix=/usr/local",
@@ -685,40 +784,44 @@
 
         if recipe.get('useLDFlags', 1):
             configure_args.extend([
-                "CFLAGS=-arch %s -isysroot %s -I%s/usr/local/include"%(
+                "CFLAGS=%s-mmacosx-version-min=%s -arch %s -isysroot %s "
+                            "-I%s/usr/local/include"%(
+                        recipe.get('extra_cflags', ''),
+                        DEPTARGET,
                         ' -arch '.join(archList),
                         shellQuote(SDKPATH)[1:-1],
                         shellQuote(basedir)[1:-1],),
-                "LDFLAGS=-syslibroot,%s -L%s/usr/local/lib -arch %s"%(
+                "LDFLAGS=-mmacosx-version-min=%s -syslibroot,%s -L%s/usr/local/lib -arch %s"%(
+                    DEPTARGET,
                     shellQuote(SDKPATH)[1:-1],
                     shellQuote(basedir)[1:-1],
                     ' -arch '.join(archList)),
             ])
         else:
             configure_args.extend([
-                "CFLAGS=-arch %s -isysroot %s -I%s/usr/local/include"%(
+                "CFLAGS=%s-mmacosx-version-min=%s -arch %s -isysroot %s "
+                            "-I%s/usr/local/include"%(
+                        recipe.get('extra_cflags', ''),
+                        DEPTARGET,
                         ' -arch '.join(archList),
                         shellQuote(SDKPATH)[1:-1],
                         shellQuote(basedir)[1:-1],),
             ])
 
         if 'configure_post' in recipe:
-            configure_args = configure_args = list(recipe['configure_post'])
+            configure_args = configure_args + list(recipe['configure_post'])
 
         configure_args.insert(0, configure)
         configure_args = [ shellQuote(a) for a in configure_args ]
 
-        if 'configure_env' in recipe:
-            configure_args.insert(0, recipe['configure_env'])
-
-        print "Running configure for %s"%(name,)
+        print("Running configure for %s"%(name,))
         runCommand(' '.join(configure_args) + ' 2>&1')
 
-    print "Running install for %s"%(name,)
+    print("Running install for %s"%(name,))
     runCommand('{ ' + install + ' ;} 2>&1')
 
-    print "Done %s"%(name,)
-    print ""
+    print("Done %s"%(name,))
+    print("")
 
     os.chdir(curdir)
 
@@ -726,9 +829,9 @@
     """
     Build our dependencies into $WORKDIR/libraries/usr/local
     """
-    print ""
-    print "Building required libraries"
-    print ""
+    print("")
+    print("Building required libraries")
+    print("")
     universal = os.path.join(WORKDIR, 'libraries')
     os.mkdir(universal)
     os.makedirs(os.path.join(universal, 'usr', 'local', 'lib'))
@@ -742,7 +845,7 @@
 def buildPythonDocs():
     # This stores the documentation as Resources/English.lproj/Documentation
     # inside the framwork. pydoc and IDLE will pick it up there.
-    print "Install python documentation"
+    print("Install python documentation")
     rootDir = os.path.join(WORKDIR, '_root')
     buildDir = os.path.join('../../Doc')
     docdir = os.path.join(rootDir, 'pydocs')
@@ -757,7 +860,7 @@
 
 
 def buildPython():
-    print "Building a universal python for %s architectures" % UNIVERSALARCHS
+    print("Building a universal python for %s architectures" % UNIVERSALARCHS)
 
     buildDir = os.path.join(WORKDIR, '_bld', 'python')
     rootDir = os.path.join(WORKDIR, '_root')
@@ -785,7 +888,7 @@
     # will find them during its extension import sanity checks.
     os.environ['DYLD_LIBRARY_PATH'] = os.path.join(WORKDIR,
                                         'libraries', 'usr', 'local', 'lib')
-    print "Running configure..."
+    print("Running configure...")
     runCommand("%s -C --enable-framework --enable-universalsdk=%s "
                "--with-universal-archs=%s "
                "%s "
@@ -797,19 +900,19 @@
         shellQuote(WORKDIR)[1:-1],
         shellQuote(WORKDIR)[1:-1]))
 
-    print "Running make"
+    print("Running make")
     runCommand("make")
 
-    print "Running make install"
+    print("Running make install")
     runCommand("make install DESTDIR=%s"%(
         shellQuote(rootDir)))
 
-    print "Running make frameworkinstallextras"
+    print("Running make frameworkinstallextras")
     runCommand("make frameworkinstallextras DESTDIR=%s"%(
         shellQuote(rootDir)))
 
     del os.environ['DYLD_LIBRARY_PATH']
-    print "Copying required shared libraries"
+    print("Copying required shared libraries")
     if os.path.exists(os.path.join(WORKDIR, 'libraries', 'Library')):
         runCommand("mv %s/* %s"%(
             shellQuote(os.path.join(
@@ -820,16 +923,16 @@
                 'Python.framework', 'Versions', getVersion(),
                 'lib'))))
 
-    print "Fix file modes"
+    print("Fix file modes")
     frmDir = os.path.join(rootDir, 'Library', 'Frameworks', 'Python.framework')
     gid = grp.getgrnam('admin').gr_gid
 
+    shared_lib_error = False
     for dirpath, dirnames, filenames in os.walk(frmDir):
         for dn in dirnames:
-            os.chmod(os.path.join(dirpath, dn), 0775)
+            os.chmod(os.path.join(dirpath, dn), STAT_0o775)
             os.chown(os.path.join(dirpath, dn), -1, gid)
 
-
         for fn in filenames:
             if os.path.islink(fn):
                 continue
@@ -840,6 +943,19 @@
             os.chmod(p, stat.S_IMODE(st.st_mode) | stat.S_IWGRP)
             os.chown(p, -1, gid)
 
+            if fn in EXPECTED_SHARED_LIBS:
+                # check to see that this file was linked with the
+                # expected library path and version
+                data = captureCommand("otool -L %s" % shellQuote(p))
+                for sl in EXPECTED_SHARED_LIBS[fn]:
+                    if ("\t%s " % sl) not in data:
+                        print("Expected shared lib %s was not linked with %s"
+                                % (sl, p))
+                        shared_lib_error = True
+
+    if shared_lib_error:
+        fatal("Unexpected shared library errors.")
+
     if PYTHON_3:
         LDVERSION=None
         VERSION=None
@@ -863,19 +979,26 @@
 
     # We added some directories to the search path during the configure
     # phase. Remove those because those directories won't be there on
-    # the end-users system.
-    path =os.path.join(rootDir, 'Library', 'Frameworks', 'Python.framework',
-                'Versions', version, 'lib', 'python%s'%(version,),
-                'config' + config_suffix, 'Makefile')
-    fp = open(path, 'r')
-    data = fp.read()
-    fp.close()
+    # the end-users system. Also remove the directories from _sysconfigdata.py
+    # (added in 3.3) if it exists.
 
-    data = data.replace('-L%s/libraries/usr/local/lib'%(WORKDIR,), '')
-    data = data.replace('-I%s/libraries/usr/local/include'%(WORKDIR,), '')
-    fp = open(path, 'w')
-    fp.write(data)
-    fp.close()
+    path_to_lib = os.path.join(rootDir, 'Library', 'Frameworks',
+                                'Python.framework', 'Versions',
+                                version, 'lib', 'python%s'%(version,))
+    paths = [os.path.join(path_to_lib, 'config' + config_suffix, 'Makefile'),
+             os.path.join(path_to_lib, '_sysconfigdata.py')]
+    for path in paths:
+        if not os.path.exists(path):
+            continue
+        fp = open(path, 'r')
+        data = fp.read()
+        fp.close()
+
+        data = data.replace(' -L%s/libraries/usr/local/lib'%(WORKDIR,), '')
+        data = data.replace(' -I%s/libraries/usr/local/include'%(WORKDIR,), '')
+        fp = open(path, 'w')
+        fp.write(data)
+        fp.close()
 
     # Add symlinks in /usr/local/bin, using relative links
     usr_local_bin = os.path.join(rootDir, 'usr', 'local', 'bin')
@@ -907,17 +1030,17 @@
 
     # This one is not handy as a template variable
     data = data.replace('$PYTHONFRAMEWORKINSTALLDIR', '/Library/Frameworks/Python.framework')
-    fp = open(outPath, 'wb')
+    fp = open(outPath, 'w')
     fp.write(data)
     fp.close()
 
 def patchScript(inPath, outPath):
     data = fileContents(inPath)
     data = data.replace('@PYVER@', getVersion())
-    fp = open(outPath, 'wb')
+    fp = open(outPath, 'w')
     fp.write(data)
     fp.close()
-    os.chmod(outPath, 0755)
+    os.chmod(outPath, STAT_0o755)
 
 
 
@@ -934,7 +1057,7 @@
         readme = textwrap.dedent(recipe['readme'])
         isRequired = recipe.get('required', True)
 
-        print "- building package %s"%(pkgname,)
+        print("- building package %s"%(pkgname,))
 
         # Substitute some variables
         textvars = dict(
@@ -979,7 +1102,7 @@
             patchScript(postflight, os.path.join(rsrcDir, 'postflight'))
 
         vers = getFullVersion()
-        major, minor = map(int, getVersion().split('.', 2))
+        major, minor = getVersionMajorMinor()
         pl = Plist(
                 CFBundleGetInfoString="Python.%s %s"%(pkgname, vers,),
                 CFBundleIdentifier='org.python.Python.%s'%(pkgname,),
@@ -1016,7 +1139,7 @@
 def makeMpkgPlist(path):
 
     vers = getFullVersion()
-    major, minor = map(int, getVersion().split('.', 2))
+    major, minor = getVersionMajorMinor()
 
     pl = Plist(
             CFBundleGetInfoString="Python %s"%(vers,),
@@ -1127,7 +1250,7 @@
     # Custom icon for the DMG, shown when the DMG is mounted.
     shutil.copy("../Icons/Disk Image.icns",
             os.path.join(WORKDIR, "mnt", volname, ".VolumeIcon.icns"))
-    runCommand("/Developer/Tools/SetFile -a C %s/"%(
+    runCommand("SetFile -a C %s/"%(
             shellQuote(os.path.join(WORKDIR, "mnt", volname)),))
 
     runCommand("hdiutil detach %s"%(shellQuote(os.path.join(WORKDIR, "mnt", volname))))
@@ -1168,6 +1291,7 @@
 
     os.environ['MACOSX_DEPLOYMENT_TARGET'] = DEPTARGET
     os.environ['CC'] = CC
+    os.environ['CXX'] = CXX
 
     if os.path.exists(WORKDIR):
         shutil.rmtree(WORKDIR)
@@ -1198,7 +1322,7 @@
 
     folder = os.path.join(WORKDIR, "_root", "Applications", "Python %s"%(
         getVersion(),))
-    os.chmod(folder, 0755)
+    os.chmod(folder, STAT_0o755)
     setIcon(folder, "../Icons/Python Folder.icns")
 
     # Create the installer
@@ -1211,9 +1335,9 @@
     shutil.copy('../../LICENSE', os.path.join(WORKDIR, 'installer', 'License.txt'))
 
     fp = open(os.path.join(WORKDIR, 'installer', 'Build.txt'), 'w')
-    print >> fp, "# BUILD INFO"
-    print >> fp, "# Date:", time.ctime()
-    print >> fp, "# By:", pwd.getpwuid(os.getuid()).pw_gecos
+    fp.write("# BUILD INFO\n")
+    fp.write("# Date: %s\n" % time.ctime())
+    fp.write("# By: %s\n" % pwd.getpwuid(os.getuid()).pw_gecos)
     fp.close()
 
     # And copy it to a DMG
diff --git a/Mac/BuildScript/ncurses-5.5.patch b/Mac/BuildScript/ncurses-5.5.patch
deleted file mode 100644
--- a/Mac/BuildScript/ncurses-5.5.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-diff -r -u ncurses-5.5-orig/test/Makefile.in ncurses-5.5/test/Makefile.in
---- ncurses-5.5-orig/test/Makefile.in	2006-03-24 12:47:40.000000000 +0100
-+++ ncurses-5.5/test/Makefile.in	2006-03-24 12:47:50.000000000 +0100
-@@ -75,7 +75,7 @@
- MATH_LIB	= @MATH_LIB@
- 
- LD		= @LD@
--LINK		= @LINK_TESTS@ $(LIBTOOL_LINK) $(CC) $(CFLAGS)
-+LINK		= @LINK_TESTS@ $(LIBTOOL_LINK) $(CC) 
- 
- usFLAGS		= @LD_MODEL@ @LOCAL_LDFLAGS@ @LDFLAGS@
- 
-diff -ru ncurses-5.5-orig/ncurses/tinfo/read_entry.c ncurses-5.5/ncurses/tinfo/read_entry.c
---- ncurses-5.5-orig/ncurses/tinfo/read_entry.c 2004-01-11 02:57:05.000000000 +0100
-+++ ncurses-5.5/ncurses/tinfo/read_entry.c      2006-03-25 22:49:39.000000000 +0100
-@@ -474,7 +474,7 @@
-     }
- 
-     /* truncate the terminal name to prevent buffer overflow */
--    (void) sprintf(ttn, "%c/%.*s", *tn, (int) sizeof(ttn) - 3, tn);
-+    (void) sprintf(ttn, "%x/%.*s", *tn, (int) sizeof(ttn) - 3, tn);
- 
-     /* This is System V behavior, in conjunction with our requirements for
-      * writing terminfo entries.
-diff -ru ncurses-5.5-orig/configure ncurses-5.5/configure
---- ncurses-5.5-orig/configure	2005-09-24 23:50:50.000000000 +0200
-+++ ncurses-5.5/configure	2006-03-26 22:24:59.000000000 +0200
-@@ -5027,7 +5027,7 @@
- 	darwin*)
- 		EXTRA_CFLAGS="-no-cpp-precomp"
- 		CC_SHARED_OPTS="-dynamic"
--		MK_SHARED_LIB='$(CC) -dynamiclib -install_name $(DESTDIR)$(libdir)/`basename $@` -compatibility_version $(ABI_VERSION) -current_version $(ABI_VERSION) -o $@'
-+		MK_SHARED_LIB='$(CC) $(CFLAGS) -dynamiclib -install_name $(DESTDIR)$(libdir)/`basename $@` -compatibility_version $(ABI_VERSION) -current_version $(ABI_VERSION) -o $@'
- 		test "$cf_cv_shlib_version" = auto && cf_cv_shlib_version=abi
- 		cf_cv_shlib_version_infix=yes
- 		;;
diff --git a/Mac/BuildScript/resources/ReadMe.txt b/Mac/BuildScript/resources/ReadMe.txt
--- a/Mac/BuildScript/resources/ReadMe.txt
+++ b/Mac/BuildScript/resources/ReadMe.txt
@@ -5,8 +5,15 @@
 Installation requires approximately $INSTALL_SIZE MB of disk space,
 ignore the message that it will take zero bytes.
 
-You must install onto your current boot disk, even though the
-installer does not enforce this, otherwise things will not work.
+If you are attempting to install on an OS X 10.8 system, you may
+see a message that Python can't be installed because it is from an
+unidentified developer.  This is because this Python installer
+package is not yet compatible with the Gatekeeper security feature
+introduced in OS X 10.8.  To allow Python to be installed, you
+can override the Gatekeeper policy for this install.  In the Finder,
+instead of double-clicking, control-click or right click the "Python"
+installer package icon.  Then select "Open using ... Installer" from
+the contextual menu that appears.
 
 Python consists of the Python programming language interpreter, plus
 a set of programs to allow easy access to it for Mac users including
@@ -16,15 +23,16 @@
 
                     **** IMPORTANT ****
                     
-Before using IDLE or other programs using the tkinter graphical user
-interface toolkit, visit http://www.python.org/download/mac/tcltk/
-for current information about supported and recommended versions
-of Tcl/Tk for this version of Python and Mac OS X.
+To use IDLE or other programs that use the tkinter graphical user
+interface toolkit, you may need to install a third-party version of
+the Tcl/Tk frameworks.  Visit http://www.python.org/download/mac/tcltk/
+for current information about supported and recommended versions of
+Tcl/Tk for this version of Python and of Mac OS X.
 
                     *******************
 
 The installer puts applications, an "Update Shell Profile" command,
-and an Extras folder containing demo programs and tools into the
+and a link to the optionally installed Python Documentation into the
 "Python $VERSION" subfolder of the system Applications folder,
 and puts the underlying machinery into the folder
 $PYTHONFRAMEWORKINSTALLDIR. It can
@@ -32,5 +40,13 @@
 well. Double-click on the "Update Shell Profile" command to add the
 "bin" directory inside the framework to your shell's search path.
 
+You must install onto your current boot disk, even though the
+installer does not enforce this, otherwise things will not work.
+
+You can verify the integrity of the disk image file containing the
+installer package and this ReadMe file by comparing its md5 checksum
+and size with the values published on the release page linked at
+http://www.python.org/download/
+
 More information on Python in general can be found at
 http://www.python.org.
diff --git a/Mac/BuildScript/scripts/postflight.documentation b/Mac/BuildScript/scripts/postflight.documentation
--- a/Mac/BuildScript/scripts/postflight.documentation
+++ b/Mac/BuildScript/scripts/postflight.documentation
@@ -5,19 +5,10 @@
 FWK_DOCDIR_SUBPATH="Resources/English.lproj/Documentation"
 FWK_DOCDIR="${FWK}/${FWK_DOCDIR_SUBPATH}"
 APPDIR="/Applications/Python ${PYVER}"
-DEV_DOCDIR="/Developer/Documentation"
 SHARE_DIR="${FWK}/share"
 SHARE_DOCDIR="${SHARE_DIR}/doc/python${PYVER}"
 SHARE_DOCDIR_TO_FWK="../../.."
 
-# make link in /Developer/Documentation/ for Xcode users
-if [ -d "${DEV_DOCDIR}" ]; then
-    if [ ! -d "${DEV_DOCDIR}/Python" ]; then
-        mkdir -p "${DEV_DOCDIR}/Python"
-    fi
-    ln -fhs "${FWK_DOCDIR}" "${DEV_DOCDIR}/Python/Reference Documentation ${PYVER}"
-fi
-
 # make link in /Applications/Python m.n/ for Finder users
 if [ -d "${APPDIR}" ]; then
     ln -fhs "${FWK_DOCDIR}/index.html" "${APPDIR}/Python Documentation.html"
diff --git a/Mac/BuildScript/scripts/postflight.framework b/Mac/BuildScript/scripts/postflight.framework
--- a/Mac/BuildScript/scripts/postflight.framework
+++ b/Mac/BuildScript/scripts/postflight.framework
@@ -8,14 +8,24 @@
 
 "${FWK}/bin/python at PYVER@" -Wi -tt \
     "${FWK}/lib/python${PYVER}/compileall.py" \
-    -x badsyntax -x site-packages \
+    -f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \
     "${FWK}/lib/python${PYVER}"
 
 "${FWK}/bin/python at PYVER@" -Wi -tt -O \
     "${FWK}/lib/python${PYVER}/compileall.py" \
-    -x badsyntax -x site-packages \
+    -f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \
     "${FWK}/lib/python${PYVER}"
 
+"${FWK}/bin/python at PYVER@" -Wi \
+    "${FWK}/lib/python${PYVER}/compileall.py" \
+    -f -x badsyntax \
+    "${FWK}/lib/python${PYVER}/site-packages"
+
+"${FWK}/bin/python at PYVER@" -Wi -O \
+    "${FWK}/lib/python${PYVER}/compileall.py" \
+    -f -x badsyntax \
+    "${FWK}/lib/python${PYVER}/site-packages"
+
 chgrp -R admin "${FWK}"
 chmod -R g+w "${FWK}"
 
diff --git a/Mac/Makefile.in b/Mac/Makefile.in
--- a/Mac/Makefile.in
+++ b/Mac/Makefile.in
@@ -38,10 +38,10 @@
 INSTALL_DATA=@INSTALL_DATA@
 LN=@LN@
 STRIPFLAG=-s
-CPMAC=/Developer/Tools/CpMac
+CPMAC=CpMac
 
 APPTEMPLATE=$(srcdir)/Resources/app
-APPSUBDIRS=MacOS Resources 
+APPSUBDIRS=MacOS Resources
 CACHERSRC=$(srcdir)/scripts/cachersrc.py
 compileall=$(srcdir)/../Lib/compileall.py
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list