--- /dev/null
+diff -up Python-2.7.3/Lib/pydoc.py.no_gui Python-2.7.3/Lib/pydoc.py
+--- Python-2.7.3/Lib/pydoc.py.no_gui 2012-04-09 19:07:31.000000000 -0400
++++ Python-2.7.3/Lib/pydoc.py 2013-02-19 13:48:44.480054515 -0500
+@@ -19,9 +19,6 @@ of all available modules.
+ local machine to generate documentation web pages. Port number 0 can be
+ used to get an arbitrary unused port.
+
+-For platforms without a command line, "pydoc -g" starts the HTTP server
+-and also pops up a little window for controlling it.
+-
+ Run "pydoc -w <name>" to write out the HTML documentation for a module
+ to a file named "<name>.html".
+
+@@ -2346,13 +2340,10 @@ def cli():
+ Start an HTTP server on the given port on the local machine. Port
+ number 0 can be used to get an arbitrary unused port.
+
+-%s -g
+- Pop up a graphical interface for finding and serving documentation.
+-
+ %s -w <name> ...
+ Write out the HTML documentation for a module to a file in the current
+ directory. If <name> contains a '%s', it is treated as a filename; if
+ it names a directory, documentation is written for all the contents.
+-""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
++""" % (cmd, os.sep, cmd, cmd, cmd, os.sep)
+
+ if __name__ == '__main__': cli()
--- /dev/null
+diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py
+index ab10ec5..923d1b7 100644
+--- a/Lib/ctypes/util.py
++++ b/Lib/ctypes/util.py
+@@ -140,11 +140,15 @@ elif os.name == "posix":
+ # assuming GNU binutils / ELF
+ if not f:
+ return None
+- cmd = 'if ! type objdump >/dev/null 2>&1; then exit; fi;' \
++ cmd = 'if ! type objdump >/dev/null 2>&1; then exit 10; fi;' \
+ 'objdump -p -j .dynamic 2>/dev/null "$1"'
+ proc = subprocess.Popen((cmd, '_get_soname', f), shell=True,
+ stdout=subprocess.PIPE)
+ [dump, _] = proc.communicate()
++ if proc.returncode == 10:
++ return os.path.basename(f) # This is good for GLibc, I think,
++ # and a dep on binutils is big (for
++ # live CDs).
+ res = re.search(br'\sSONAME\s+([^\s]+)', dump)
+ if not res:
+ return None
+++ /dev/null
-diff -up Python-2.7.3/Lib/test/test_re.py.lib64-regex Python-2.7.3/Lib/test/test_re.py
---- Python-2.7.3/Lib/test/test_re.py.lib64-regex 2012-04-09 19:07:32.000000000 -0400
-+++ Python-2.7.3/Lib/test/test_re.py 2013-02-19 13:53:57.624033102 -0500
-@@ -757,6 +757,15 @@ class ReTests(unittest.TestCase):
- self.assertRaises(TypeError, re.finditer, "a", {})
- self.assertRaises(OverflowError, _sre.compile, "abc", 0, [long_overflow])
-
-+ def test_bug_931848(self):
-+ try:
-+ unicode
-+ except NameError:
-+ pass
-+ pattern = eval('u"[\u002E\u3002\uFF0E\uFF61]"')
-+ self.assertEqual(re.compile(pattern).split("a.b.c"),
-+ ['a','b','c'])
-+
- def run_re_tests():
- from test.re_tests import tests, SUCCEED, FAIL, SYNTAX_ERROR
- if verbose:
+++ /dev/null
-diff -up Python-2.7.3/Makefile.pre.in.no-static-lib Python-2.7.3/Makefile.pre.in
---- Python-2.7.3/Makefile.pre.in.no-static-lib 2013-02-19 14:03:40.801993224 -0500
-+++ Python-2.7.3/Makefile.pre.in 2013-02-19 14:04:44.070988898 -0500
-@@ -397,7 +397,7 @@ coverage:
-
-
- # Build the interpreter
--$(BUILDPYTHON): Modules/python.o $(LIBRARY) $(LDLIBRARY)
-+$(BUILDPYTHON): Modules/python.o $(LDLIBRARY)
- $(LINKCC) $(LDFLAGS) $(LINKFORSHARED) -o $@ \
- Modules/python.o \
- $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
-@@ -413,18 +413,6 @@ sharedmods: $(BUILDPYTHON)
- $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \
- $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build
-
--# Build static library
--# avoid long command lines, same as LIBRARY_OBJS
--$(LIBRARY): $(LIBRARY_OBJS)
-- -rm -f $@
-- $(AR) $(ARFLAGS) $@ Modules/getbuildinfo.o
-- $(AR) $(ARFLAGS) $@ $(PARSER_OBJS)
-- $(AR) $(ARFLAGS) $@ $(OBJECT_OBJS)
-- $(AR) $(ARFLAGS) $@ $(PYTHON_OBJS)
-- $(AR) $(ARFLAGS) $@ $(MODULE_OBJS) $(SIGNAL_OBJS)
-- $(AR) $(ARFLAGS) $@ $(MODOBJS)
-- $(RANLIB) $@
--
- libpython$(VERSION).so: $(LIBRARY_OBJS)
- if test $(INSTSONAME) != $(LDLIBRARY); then \
- $(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \
-@@ -1021,18 +1009,6 @@ libainstall: all python-config
- else true; \
- fi; \
- done
-- @if test -d $(LIBRARY); then :; else \
-- if test "$(PYTHONFRAMEWORKDIR)" = no-framework; then \
-- if test "$(SO)" = .dll; then \
-- $(INSTALL_DATA) $(LDLIBRARY) $(DESTDIR)$(LIBPL) ; \
-- else \
-- $(INSTALL_DATA) $(LIBRARY) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \
-- $(RANLIB) $(DESTDIR)$(LIBPL)/$(LIBRARY) ; \
-- fi; \
-- else \
-- echo Skip install of $(LIBRARY) - use make frameworkinstall; \
-- fi; \
-- fi
- $(INSTALL_DATA) Modules/config.c $(DESTDIR)$(LIBPL)/config.c
- $(INSTALL_DATA) Modules/python.o $(DESTDIR)$(LIBPL)/python.o
- $(INSTALL_DATA) $(srcdir)/Modules/config.c.in $(DESTDIR)$(LIBPL)/config.c.in
--- /dev/null
+From 898f93aa206e577dfe854c59bc62d0cea09cd5ed Mon Sep 17 00:00:00 2001
+From: Tomas Orsava <torsava@redhat.com>
+Date: Tue, 10 Jan 2017 16:19:50 +0100
+Subject: [PATCH] Patch to support building both optimized vs debug stacks DSO
+ ABIs,
+
+sharing the same .py and .pyc files, using "_d.so" to signify a debug build of
+an extension module.
+---
+ Lib/distutils/command/build_ext.py | 7 ++++-
+ Lib/distutils/sysconfig.py | 5 ++--
+ Lib/distutils/tests/test_install.py | 3 +-
+ Makefile.pre.in | 56 ++++++++++++++++++++-----------------
+ Misc/python-config.in | 2 +-
+ Modules/makesetup | 2 +-
+ Python/dynload_shlib.c | 11 ++++++--
+ Python/sysmodule.c | 6 ++++
+ configure.ac | 14 ++++++++--
+ 9 files changed, 69 insertions(+), 37 deletions(-)
+
+diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py
+index 2c68be3..029d144 100644
+--- a/Lib/distutils/command/build_ext.py
++++ b/Lib/distutils/command/build_ext.py
+@@ -677,7 +677,10 @@ class build_ext (Command):
+ so_ext = get_config_var('SO')
+ if os.name == 'nt' and self.debug:
+ return os.path.join(*ext_path) + '_d' + so_ext
+- return os.path.join(*ext_path) + so_ext
++
++ # Similarly, extensions in debug mode are named 'module_d.so', to
++ # avoid adding the _d to the SO config variable:
++ return os.path.join(*ext_path) + (sys.pydebug and "_d" or "") + so_ext
+
+ def get_export_symbols (self, ext):
+ """Return the list of symbols that a shared extension has to
+@@ -762,6 +765,8 @@ class build_ext (Command):
+ template = "python%d.%d"
+ pythonlib = (template %
+ (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
++ if sys.pydebug:
++ pythonlib += '_d'
+ return ext.libraries + [pythonlib]
+ else:
+ return ext.libraries
+diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
+index 3e7f077..ec5d584 100644
+--- a/Lib/distutils/sysconfig.py
++++ b/Lib/distutils/sysconfig.py
+@@ -90,7 +90,8 @@ def get_python_inc(plat_specific=0, prefix=None):
+ # Include is located in the srcdir
+ inc_dir = os.path.join(srcdir, "Include")
+ return inc_dir
+- return os.path.join(prefix, "include", "python" + get_python_version())
++ return os.path.join(prefix, "include",
++ "python" + get_python_version() + (sys.pydebug and '-debug' or ''))
+ elif os.name == "nt":
+ return os.path.join(prefix, "include")
+ elif os.name == "os2":
+@@ -248,7 +249,7 @@ def get_makefile_filename():
+ if python_build:
+ return os.path.join(project_base, "Makefile")
+ lib_dir = get_python_lib(plat_specific=1, standard_lib=1)
+- return os.path.join(lib_dir, "config", "Makefile")
++ return os.path.join(lib_dir, "config" + (sys.pydebug and "-debug" or ""), "Makefile")
+
+
+ def parse_config_h(fp, g=None):
+diff --git a/Lib/distutils/tests/test_install.py b/Lib/distutils/tests/test_install.py
+index 78fac46..d1d0931 100644
+--- a/Lib/distutils/tests/test_install.py
++++ b/Lib/distutils/tests/test_install.py
+@@ -20,8 +20,9 @@ from distutils.tests import support
+
+
+ def _make_ext_name(modname):
+- if os.name == 'nt' and sys.executable.endswith('_d.exe'):
++ if sys.pydebug:
+ modname += '_d'
++
+ return modname + sysconfig.get_config_var('SO')
+
+
+diff --git a/Makefile.pre.in b/Makefile.pre.in
+index 997a2fc..467e782 100644
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -116,8 +116,8 @@ SCRIPTDIR= $(prefix)/lib64
+ # Detailed destination directories
+ BINLIBDEST= $(LIBDIR)/python$(VERSION)
+ LIBDEST= $(SCRIPTDIR)/python$(VERSION)
+-INCLUDEPY= $(INCLUDEDIR)/python$(VERSION)
+-CONFINCLUDEPY= $(CONFINCLUDEDIR)/python$(VERSION)
++INCLUDEPY= $(INCLUDEDIR)/python$(VERSION)$(DEBUG_SUFFIX)
++CONFINCLUDEPY= $(CONFINCLUDEDIR)/python$(VERSION)$(DEBUG_SUFFIX)
+ LIBP= $(LIBDIR)/python$(VERSION)
+
+ # Symbols used for using shared libraries
+@@ -131,6 +131,12 @@ DESTSHARED= $(BINLIBDEST)/lib-dynload
+ EXE= @EXEEXT@
+ BUILDEXE= @BUILDEXEEXT@
+
++# DEBUG_EXT is used by ELF files (names and SONAMEs); it will be "_d" for a debug build
++# DEBUG_SUFFIX is used by filesystem paths; it will be "-debug" for a debug build
++# Both will be empty in an optimized build
++DEBUG_EXT= @DEBUG_EXT@
++DEBUG_SUFFIX= @DEBUG_SUFFIX@
++
+ # Short name and location for Mac OS X Python framework
+ UNIVERSALSDK=@UNIVERSALSDK@
+ PYTHONFRAMEWORK= @PYTHONFRAMEWORK@
+@@ -197,8 +203,8 @@ LIBOBJDIR= Python/
+ LIBOBJS= @LIBOBJS@
+ UNICODE_OBJS= @UNICODE_OBJS@
+
+-PYTHON= python$(EXE)
+-BUILDPYTHON= python$(BUILDEXE)
++PYTHON= python$(DEBUG_SUFFIX)$(EXE)
++BUILDPYTHON= python$(DEBUG_SUFFIX)$(BUILDEXE)
+
+ PYTHON_FOR_REGEN=@PYTHON_FOR_REGEN@
+ PYTHON_FOR_BUILD=@PYTHON_FOR_BUILD@
+@@ -547,7 +553,7 @@ sharedmods: $(BUILDPYTHON) pybuilddir.txt Modules/_math.o
+ _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \
+ $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build
+
+-libpython$(VERSION).so: $(LIBRARY_OBJS)
++libpython$(VERSION)$(DEBUG_EXT).so: $(LIBRARY_OBJS)
+ if test $(INSTSONAME) != $(LDLIBRARY); then \
+ $(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \
+ $(LN) -f $(INSTSONAME) $@; \
+@@ -954,18 +960,18 @@ bininstall: altbininstall
+ then rm -f $(DESTDIR)$(BINDIR)/$(PYTHON); \
+ else true; \
+ fi
+- (cd $(DESTDIR)$(BINDIR); $(LN) -s python2$(EXE) $(PYTHON))
+- -rm -f $(DESTDIR)$(BINDIR)/python2$(EXE)
+- (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)$(EXE) python2$(EXE))
+- -rm -f $(DESTDIR)$(BINDIR)/python2-config
+- (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)-config python2-config)
+- -rm -f $(DESTDIR)$(BINDIR)/python-config
+- (cd $(DESTDIR)$(BINDIR); $(LN) -s python2-config python-config)
++ (cd $(DESTDIR)$(BINDIR); $(LN) -s python2$(DEBUG_SUFFIX)$(EXE) $(PYTHON))
++ -rm -f $(DESTDIR)$(BINDIR)/python2$(DEBUG_SUFFIX)$(EXE)
++ (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)$(DEBUG_SUFFIX)$(EXE) python2$(DEBUG_SUFFIX)$(EXE))
++ -rm -f $(DESTDIR)$(BINDIR)/python2$(DEBUG_SUFFIX)-config
++ (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)$(DEBUG_SUFFIX)-config python2$(DEBUG_SUFFIX)-config)
++ -rm -f $(DESTDIR)$(BINDIR)/python$(DEBUG_SUFFIX)-config
++ (cd $(DESTDIR)$(BINDIR); $(LN) -s python2$(DEBUG_SUFFIX)-config python$(DEBUG_SUFFIX)-config)
+ -test -d $(DESTDIR)$(LIBPC) || $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(LIBPC)
+- -rm -f $(DESTDIR)$(LIBPC)/python2.pc
+- (cd $(DESTDIR)$(LIBPC); $(LN) -s python-$(VERSION).pc python2.pc)
+- -rm -f $(DESTDIR)$(LIBPC)/python.pc
+- (cd $(DESTDIR)$(LIBPC); $(LN) -s python2.pc python.pc)
++ -rm -f $(DESTDIR)$(LIBPC)/python2$(DEBUG_SUFFIX).pc
++ (cd $(DESTDIR)$(LIBPC); $(LN) -s python-$(VERSION)$(DEBUG_SUFFIX).pc python2$(DEBUG_SUFFIX).pc)
++ -rm -f $(DESTDIR)$(LIBPC)/python$(DEBUG_SUFFIX).pc
++ (cd $(DESTDIR)$(LIBPC); $(LN) -s python2$(DEBUG_SUFFIX).pc python$(DEBUG_SUFFIX).pc)
+
+ # Install the interpreter with $(VERSION) affixed
+ # This goes into $(exec_prefix)
+@@ -978,7 +984,7 @@ altbininstall: $(BUILDPYTHON)
+ else true; \
+ fi; \
+ done
+- $(INSTALL_PROGRAM) $(BUILDPYTHON) $(DESTDIR)$(BINDIR)/python$(VERSION)$(EXE)
++ $(INSTALL_PROGRAM) $(BUILDPYTHON) $(DESTDIR)$(BINDIR)/python$(VERSION)$(DEBUG_SUFFIX)$(EXE)
+ if test -f $(LDLIBRARY); then \
+ if test -n "$(DLLLIBRARY)" ; then \
+ $(INSTALL_SHARED) $(DLLLIBRARY) $(DESTDIR)$(BINDIR); \
+@@ -1148,10 +1154,11 @@ $(srcdir)/Lib/$(PLATDIR):
+ fi; \
+ cd $(srcdir)/Lib/$(PLATDIR); $(RUNSHARED) ./regen
+
+-python-config: $(srcdir)/Misc/python-config.in
++python$(DEBUG_SUFFIX)-config: $(srcdir)/Misc/python-config.in
+ # Substitution happens here, as the completely-expanded BINDIR
+ # is not available in configure
+- sed -e "s,@EXENAME@,$(BINDIR)/python$(VERSION)$(EXE)," < $(srcdir)/Misc/python-config.in >python-config
++ sed -e "s,@EXENAME@,$(BINDIR)/python$(VERSION)$(DEBUG_SUFFIX)$(EXE)," < $(srcdir)/Misc/python-config.in >python$(DEBUG_SUFFIX)-config
++
+
+ # Install the include files
+ INCLDIRSTOMAKE=$(INCLUDEDIR) $(CONFINCLUDEDIR) $(INCLUDEPY) $(CONFINCLUDEPY)
+@@ -1172,13 +1179,13 @@ inclinstall:
+ $(INSTALL_DATA) pyconfig.h $(DESTDIR)$(CONFINCLUDEPY)/pyconfig.h
+
+ # Install the library and miscellaneous stuff needed for extending/embedding
+-# This goes into $(exec_prefix)
+-LIBPL= $(LIBP)/config
++# This goes into $(exec_prefix)$(DEBUG_SUFFIX)
++LIBPL= $(LIBP)/config$(DEBUG_SUFFIX)
+
+ # pkgconfig directory
+ LIBPC= $(LIBDIR)/pkgconfig
+
+-libainstall: @DEF_MAKE_RULE@ python-config
++libainstall: @DEF_MAKE_RULE@ python$(DEBUG_SUFFIX)-config
+ @for i in $(LIBDIR) $(LIBP) $(LIBPL) $(LIBPC); \
+ do \
+ if test ! -d $(DESTDIR)$$i; then \
+@@ -1194,11 +1201,10 @@ libainstall: all python-config
+ $(INSTALL_DATA) Modules/Setup $(DESTDIR)$(LIBPL)/Setup
+ $(INSTALL_DATA) Modules/Setup.local $(DESTDIR)$(LIBPL)/Setup.local
+ $(INSTALL_DATA) Modules/Setup.config $(DESTDIR)$(LIBPL)/Setup.config
+- $(INSTALL_DATA) Misc/python.pc $(DESTDIR)$(LIBPC)/python-$(VERSION).pc
++ $(INSTALL_DATA) Misc/python.pc $(DESTDIR)$(LIBPC)/python-$(VERSION)$(DEBUG_SUFFIX).pc
+ $(INSTALL_SCRIPT) $(srcdir)/Modules/makesetup $(DESTDIR)$(LIBPL)/makesetup
+ $(INSTALL_SCRIPT) $(srcdir)/install-sh $(DESTDIR)$(LIBPL)/install-sh
+- $(INSTALL_SCRIPT) python-config $(DESTDIR)$(BINDIR)/python$(VERSION)-config
+- rm python-config
++ $(INSTALL_SCRIPT) python$(DEBUG_SUFFIX)-config $(DESTDIR)$(BINDIR)/python$(VERSION)$(DEBUG_SUFFIX)-config
+ @if [ -s Modules/python.exp -a \
+ "`echo $(MACHDEP) | sed 's/^\(...\).*/\1/'`" = "aix" ]; then \
+ echo; echo "Installing support files for building shared extension modules on AIX:"; \
+diff --git a/Misc/python-config.in b/Misc/python-config.in
+index a09e07c..c1691ef 100644
+--- a/Misc/python-config.in
++++ b/Misc/python-config.in
+@@ -44,7 +44,7 @@ for opt in opt_flags:
+ print ' '.join(flags)
+
+ elif opt in ('--libs', '--ldflags'):
+- libs = ['-lpython' + pyver]
++ libs = ['-lpython' + pyver + (sys.pydebug and "_d" or "")]
+ libs += getvar('LIBS').split()
+ libs += getvar('SYSLIBS').split()
+ # add the prefix/lib/pythonX.Y/config dir, but only if there is no
+diff --git a/Modules/makesetup b/Modules/makesetup
+index 1bffcbf..f0bc743 100755
+--- a/Modules/makesetup
++++ b/Modules/makesetup
+@@ -233,7 +233,7 @@ sed -e 's/[ ]*#.*//' -e '/^[ ]*$/d' |
+ *$mod.o*) base=$mod;;
+ *) base=${mod}module;;
+ esac
+- file="$srcdir/$base\$(SO)"
++ file="$srcdir/$base\$(DEBUG_EXT)\$(SO)"
+ case $doconfig in
+ no) SHAREDMODS="$SHAREDMODS $file";;
+ esac
+diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c
+index 17ebab1..02a94aa 100644
+--- a/Python/dynload_shlib.c
++++ b/Python/dynload_shlib.c
+@@ -46,11 +46,16 @@ const struct filedescr _PyImport_DynLoadFiletab[] = {
+ {"module.exe", "rb", C_EXTENSION},
+ {"MODULE.EXE", "rb", C_EXTENSION},
+ #else
++#ifdef Py_DEBUG
++ {"_d.so", "rb", C_EXTENSION},
++ {"module_d.so", "rb", C_EXTENSION},
++#else
+ {".so", "rb", C_EXTENSION},
+ {"module.so", "rb", C_EXTENSION},
+-#endif
+-#endif
+-#endif
++#endif /* Py_DEBUG */
++#endif /* __VMS */
++#endif /* defined(PYOS_OS2) && defined(PYCC_GCC) */
++#endif /* __CYGWIN__ */
+ {0, 0}
+ };
+
+diff --git a/Python/sysmodule.c b/Python/sysmodule.c
+index aeff38a..183e3cc 100644
+--- a/Python/sysmodule.c
++++ b/Python/sysmodule.c
+@@ -1524,6 +1524,12 @@ _PySys_Init(void)
+ PyString_FromString("legacy"));
+ #endif
+
++#ifdef Py_DEBUG
++ PyDict_SetItemString(sysdict, "pydebug", Py_True);
++#else
++ PyDict_SetItemString(sysdict, "pydebug", Py_False);
++#endif
++
+ #undef SET_SYS_FROM_STRING
+ if (PyErr_Occurred())
+ return NULL;
+diff --git a/configure.ac b/configure.ac
+index 0a902c7..5caedb7 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -764,7 +764,7 @@ AC_SUBST(LIBRARY)
+ AC_MSG_CHECKING(LIBRARY)
+ if test -z "$LIBRARY"
+ then
+- LIBRARY='libpython$(VERSION).a'
++ LIBRARY='libpython$(VERSION)$(DEBUG_EXT).a'
+ fi
+ AC_MSG_RESULT($LIBRARY)
+
+@@ -910,8 +910,8 @@ if test $enable_shared = "yes"; then
+ INSTSONAME="$LDLIBRARY".$SOVERSION
+ ;;
+ Linux*|GNU*|NetBSD*|FreeBSD*|DragonFly*|OpenBSD*)
+- LDLIBRARY='libpython$(VERSION).so'
+- BLDLIBRARY='-L. -lpython$(VERSION)'
++ LDLIBRARY='libpython$(VERSION)$(DEBUG_EXT).so'
++ BLDLIBRARY='-L. -lpython$(VERSION)$(DEBUG_EXT)'
+ RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
+ case $ac_sys_system in
+ FreeBSD*)
+@@ -1040,6 +1040,14 @@ else AC_MSG_RESULT(no); Py_DEBUG='false'
+ fi],
+ [AC_MSG_RESULT(no)])
+
++if test "$Py_DEBUG" = 'true'
++then
++ DEBUG_EXT=_d
++ DEBUG_SUFFIX=-debug
++fi
++AC_SUBST(DEBUG_EXT)
++AC_SUBST(DEBUG_SUFFIX)
++
+ # XXX Shouldn't the code above that fiddles with BASECFLAGS and OPT be
+ # merged with this chunk of code?
+
+--
+2.11.0
+
+++ /dev/null
-diff -up Python-2.7/Python/pythonrun.c.less-verbose-COUNT_ALLOCS Python-2.7/Python/pythonrun.c
---- Python-2.7/Python/pythonrun.c.less-verbose-COUNT_ALLOCS 2010-08-17 14:49:33.321913909 -0400
-+++ Python-2.7/Python/pythonrun.c 2010-08-17 14:54:48.750910403 -0400
-@@ -470,7 +470,15 @@ Py_Finalize(void)
-
- /* Debugging stuff */
- #ifdef COUNT_ALLOCS
-- dump_counts(stdout);
-+ /* This is a downstream Fedora modification.
-+ The upstream default with COUNT_ALLOCS is to always dump the counts to
-+ stdout on exit. For our debug builds its useful to have the info from
-+ COUNT_ALLOCS available, but the stdout info here gets in the way, so
-+ we make it optional, wrapping it in an environment variable (modelled
-+ on the other PYTHONDUMP* env variables):
-+ */
-+ if (Py_GETENV("PYTHONDUMPCOUNTS"))
-+ dump_counts(stdout);
- #endif
-
- PRINT_TOTAL_REFS();
--- /dev/null
+diff -up Python-2.7.2/Lib/unittest/case.py.add-rpmbuild-hooks-to-unittest Python-2.7.2/Lib/unittest/case.py
+--- Python-2.7.2/Lib/unittest/case.py.add-rpmbuild-hooks-to-unittest 2011-09-08 14:45:47.677169191 -0400
++++ Python-2.7.2/Lib/unittest/case.py 2011-09-08 16:01:36.287858159 -0400
+@@ -1,6 +1,7 @@
+ """Test case implementation"""
+
+ import collections
++import os
+ import sys
+ import functools
+ import difflib
+@@ -94,6 +95,43 @@ def expectedFailure(func):
+ return wrapper
+
+
++# Non-standard/downstream-only hooks for handling issues with specific test
++# cases:
++
++def _skipInRpmBuild(reason):
++ """
++ Non-standard/downstream-only decorator for marking a specific unit test
++ to be skipped when run within the %check of an rpmbuild.
++
++ Specifically, this takes effect when WITHIN_PYTHON_RPM_BUILD is set within
++ the environment, and has no effect otherwise.
++ """
++ if 'WITHIN_PYTHON_RPM_BUILD' in os.environ:
++ return skip(reason)
++ else:
++ return _id
++
++def _expectedFailureInRpmBuild(func):
++ """
++ Non-standard/downstream-only decorator for marking a specific unit test
++ as expected to fail within the %check of an rpmbuild.
++
++ Specifically, this takes effect when WITHIN_PYTHON_RPM_BUILD is set within
++ the environment, and has no effect otherwise.
++ """
++ @functools.wraps(func)
++ def wrapper(*args, **kwargs):
++ if 'WITHIN_PYTHON_RPM_BUILD' in os.environ:
++ try:
++ func(*args, **kwargs)
++ except Exception:
++ raise _ExpectedFailure(sys.exc_info())
++ raise _UnexpectedSuccess
++ else:
++ # Call directly:
++ func(*args, **kwargs)
++ return wrapper
++
+ class _AssertRaisesContext(object):
+ """A context manager used to implement TestCase.assertRaises* methods."""
+
+diff -up Python-2.7.2/Lib/unittest/__init__.py.add-rpmbuild-hooks-to-unittest Python-2.7.2/Lib/unittest/__init__.py
+--- Python-2.7.2/Lib/unittest/__init__.py.add-rpmbuild-hooks-to-unittest 2011-09-08 14:59:39.534112310 -0400
++++ Python-2.7.2/Lib/unittest/__init__.py 2011-09-08 15:07:09.191081562 -0400
+@@ -57,7 +57,8 @@ __unittest = True
+
+ from .result import TestResult
+ from .case import (TestCase, FunctionTestCase, SkipTest, skip, skipIf,
+- skipUnless, expectedFailure)
++ skipUnless, expectedFailure,
++ _skipInRpmBuild, _expectedFailureInRpmBuild)
+ from .suite import BaseTestSuite, TestSuite
+ from .loader import (TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,
+ findTestCases)
+++ /dev/null
-diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
-index 0dd4258..d9b3267 100644
---- a/Lib/test/test_sys.py
-+++ b/Lib/test/test_sys.py
-@@ -769,6 +769,11 @@ class SizeofTest(unittest.TestCase):
- '10P' # PySequenceMethods
- '6P' # PyBufferProcs
- '2P')
-+
-+ # COUNT_ALLOCS adds further fields to the end of a PyTypeObject:
-+ if hasattr(sys, 'getcounts'):
-+ s += size('P')
-+
- class newstyleclass(object):
- pass
- check(newstyleclass, s)
--- /dev/null
+diff -up Python-2.7.3/Lib/distutils/tests/test_bdist_rpm.py.mark-tests-that-fail-in-rpmbuild Python-2.7.3/Lib/distutils/tests/test_bdist_rpm.py
+--- Python-2.7.3/Lib/distutils/tests/test_bdist_rpm.py.mark-tests-that-fail-in-rpmbuild 2012-04-09 19:07:29.000000000 -0400
++++ Python-2.7.3/Lib/distutils/tests/test_bdist_rpm.py 2012-04-13 00:20:08.223819263 -0400
+@@ -24,6 +24,7 @@ setup(name='foo', version='0.1', py_modu
+
+ """
+
++@unittest._skipInRpmBuild("don't try to nest one rpm build inside another rpm build")
+ class BuildRpmTestCase(support.TempdirManager,
+ support.EnvironGuard,
+ support.LoggingSilencer,
+diff -up Python-2.7.3/Lib/distutils/tests/test_build_ext.py.mark-tests-that-fail-in-rpmbuild Python-2.7.3/Lib/distutils/tests/test_build_ext.py
--- /dev/null
+diff -up Python-2.7.2/Lib/distutils/tests/test_build_ext.py.mark-tests-that-fail-in-rpmbuild Python-2.7.2/Lib/distutils/tests/test_build_ext.py
+--- Python-2.7.2/Lib/distutils/tests/test_build_ext.py.mark-tests-that-fail-in-rpmbuild 2011-09-08 16:07:25.033834312 -0400
++++ Python-2.7.2/Lib/distutils/tests/test_build_ext.py 2011-09-08 17:43:15.656441082 -0400
+@@ -330,6 +332,7 @@ class BuildExtTestCase(support.TempdirMa
+ self.assertEqual(lastdir, 'bar')
+
+ def test_ext_fullpath(self):
++ debug_ext = sysconfig.get_config_var("DEBUG_EXT")
+ ext = sysconfig.get_config_vars()['SO']
+ dist = Distribution()
+ cmd = build_ext(dist)
+@@ -337,14 +340,14 @@ class BuildExtTestCase(support.TempdirMa
+ cmd.distribution.package_dir = {'': 'src'}
+ cmd.distribution.packages = ['lxml', 'lxml.html']
+ curdir = os.getcwd()
+- wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
++ wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + debug_ext + ext)
+ path = cmd.get_ext_fullpath('lxml.etree')
+ self.assertEqual(wanted, path)
+
+ # building lxml.etree not inplace
+ cmd.inplace = 0
+ cmd.build_lib = os.path.join(curdir, 'tmpdir')
+- wanted = os.path.join(curdir, 'tmpdir', 'lxml', 'etree' + ext)
++ wanted = os.path.join(curdir, 'tmpdir', 'lxml', 'etree' + debug_ext + ext)
+ path = cmd.get_ext_fullpath('lxml.etree')
+ self.assertEqual(wanted, path)
+
+@@ -354,13 +357,13 @@ class BuildExtTestCase(support.TempdirMa
+ cmd.distribution.packages = ['twisted', 'twisted.runner.portmap']
+ path = cmd.get_ext_fullpath('twisted.runner.portmap')
+ wanted = os.path.join(curdir, 'tmpdir', 'twisted', 'runner',
+- 'portmap' + ext)
++ 'portmap' + debug_ext + ext)
+ self.assertEqual(wanted, path)
+
+ # building twisted.runner.portmap inplace
+ cmd.inplace = 1
+ path = cmd.get_ext_fullpath('twisted.runner.portmap')
+- wanted = os.path.join(curdir, 'twisted', 'runner', 'portmap' + ext)
++ wanted = os.path.join(curdir, 'twisted', 'runner', 'portmap' + debug_ext + ext)
+ self.assertEqual(wanted, path)
+
+ def test_build_ext_inplace(self):
+@@ -373,8 +376,9 @@ class BuildExtTestCase(support.TempdirMa
+ cmd.distribution.package_dir = {'': 'src'}
+ cmd.distribution.packages = ['lxml', 'lxml.html']
+ curdir = os.getcwd()
++ debug_ext = sysconfig.get_config_var("DEBUG_EXT")
+ ext = sysconfig.get_config_var("SO")
+- wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext)
++ wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + debug_ext + ext)
+ path = cmd.get_ext_fullpath('lxml.etree')
+ self.assertEqual(wanted, path)
+
+@@ -412,10 +416,11 @@ class BuildExtTestCase(support.TempdirMa
+ dist = Distribution({'name': 'UpdateManager'})
+ cmd = build_ext(dist)
+ cmd.ensure_finalized()
++ debug_ext = sysconfig.get_config_var("DEBUG_EXT")
+ ext = sysconfig.get_config_var("SO")
+ ext_name = os.path.join('UpdateManager', 'fdsend')
+ ext_path = cmd.get_ext_fullpath(ext_name)
+- wanted = os.path.join(cmd.build_lib, 'UpdateManager', 'fdsend' + ext)
++ wanted = os.path.join(cmd.build_lib, 'UpdateManager', 'fdsend' + debug_ext + ext)
+ self.assertEqual(ext_path, wanted)
+
+ @unittest.skipUnless(sys.platform == 'win32', 'these tests require Windows')
--- /dev/null
+diff -up Python-2.7.2/Lib/test/test_float.py.skip-test_float-known-failure-on-arm Python-2.7.2/Lib/test/test_float.py
+--- Python-2.7.2/Lib/test/test_float.py.skip-test_float-known-failure-on-arm 2011-09-08 19:34:09.000986128 -0400
++++ Python-2.7.2/Lib/test/test_float.py 2011-09-08 19:34:57.969982779 -0400
+@@ -1072,6 +1072,7 @@ class HexFloatTestCase(unittest.TestCase
+ self.identical(got, expected)
+
+
++ @unittest.skip('Known failure on ARM: http://bugs.python.org/issue8265')
+ def test_from_hex(self):
+ MIN = self.MIN;
+ MAX = self.MAX;
--- /dev/null
+diff -up Python-2.7.2/Lib/ctypes/test/test_callbacks.py.skip-test_ctypes-known-failure-on-sparc Python-2.7.2/Lib/ctypes/test/test_callbacks.py
+--- Python-2.7.2/Lib/ctypes/test/test_callbacks.py.skip-test_ctypes-known-failure-on-sparc 2011-09-08 19:42:35.541951490 -0400
++++ Python-2.7.2/Lib/ctypes/test/test_callbacks.py 2011-09-08 19:43:40.676947036 -0400
+@@ -67,6 +67,7 @@ class Callbacks(unittest.TestCase):
+ self.check_type(c_longlong, 42)
+ self.check_type(c_longlong, -42)
+
++ @unittest.skip('Known failure on Sparc: http://bugs.python.org/issue8314')
+ def test_ulonglong(self):
+ # test some 64-bit values, with and without msb set.
+ self.check_type(c_ulonglong, 10955412242170339782)
+++ /dev/null
-diff -up Python-2.7.2/Lib/test/test_gc.py.fix-test_gc_with_COUNT_ALLOCS Python-2.7.2/Lib/test/test_gc.py
---- Python-2.7.2/Lib/test/test_gc.py.fix-test_gc_with_COUNT_ALLOCS 2011-09-08 19:49:13.045924309 -0400
-+++ Python-2.7.2/Lib/test/test_gc.py 2011-09-08 19:50:07.035920617 -0400
-@@ -102,11 +102,17 @@ class GCTests(unittest.TestCase):
- del a
- self.assertNotEqual(gc.collect(), 0)
- del B, C
-- self.assertNotEqual(gc.collect(), 0)
-+ if hasattr(sys, 'getcounts'):
-+ self.assertEqual(gc.collect(), 0)
-+ else:
-+ self.assertNotEqual(gc.collect(), 0)
- A.a = A()
- del A
-- self.assertNotEqual(gc.collect(), 0)
-- self.assertEqual(gc.collect(), 0)
-+ if hasattr(sys, 'getcounts'):
-+ self.assertEqual(gc.collect(), 0)
-+ else:
-+ self.assertNotEqual(gc.collect(), 0)
-+ self.assertEqual(gc.collect(), 0)
-
- def test_method(self):
- # Tricky: self.__init__ is a bound method, it references the instance.
-diff -up Python-2.7.2/Lib/test/test_openpty.py.skip-failing-pty-tests-in-rpmbuild Python-2.7.2/Lib/test/test_openpty.py
---- Python-2.7.2/Lib/test/test_openpty.py.skip-failing-pty-tests-in-rpmbuild 2011-09-09 05:09:28.698920379 -0400
-+++ Python-2.7.2/Lib/test/test_openpty.py 2011-09-09 05:10:54.805914490 -0400
+diff -up Python-2.7.6/Lib/test/test_openpty.py.tty-fail Python-2.7.6/Lib/test/test_openpty.py
+--- Python-2.7.6/Lib/test/test_openpty.py.tty-fail 2014-01-29 14:31:43.761343267 +0100
++++ Python-2.7.6/Lib/test/test_openpty.py 2014-01-29 14:32:19.284090165 +0100
@@ -8,6 +8,7 @@ if not hasattr(os, "openpty"):
+ @unittest._skipInRpmBuild('sometimes fails in Koji, possibly due to a mock issue (rhbz#714627)')
def test(self):
master, slave = os.openpty()
- if not os.isatty(slave):
-diff -up Python-2.7.2/Lib/test/test_pty.py.skip-failing-pty-tests-in-rpmbuild Python-2.7.2/Lib/test/test_pty.py
---- Python-2.7.2/Lib/test/test_pty.py.skip-failing-pty-tests-in-rpmbuild 2011-09-09 05:09:36.781919825 -0400
-+++ Python-2.7.2/Lib/test/test_pty.py 2011-09-09 05:11:14.741913127 -0400
-@@ -109,6 +109,7 @@ class PtyTest(unittest.TestCase):
+ self.addCleanup(os.close, master)
+diff -up Python-2.7.6/Lib/test/test_pty.py.tty-fail Python-2.7.6/Lib/test/test_pty.py
+--- Python-2.7.6/Lib/test/test_pty.py.tty-fail 2013-11-10 08:36:40.000000000 +0100
++++ Python-2.7.6/Lib/test/test_pty.py 2014-01-29 14:31:43.761343267 +0100
+@@ -111,6 +111,7 @@ class PtyTest(unittest.TestCase):
os.close(master_fd)
--- /dev/null
+diff -up Python-2.7.2/Python/ceval.c.tsc-on-ppc Python-2.7.2/Python/ceval.c
+--- Python-2.7.2/Python/ceval.c.tsc-on-ppc 2011-08-23 14:59:48.051300849 -0400
++++ Python-2.7.2/Python/ceval.c 2011-08-23 15:33:25.412162902 -0400
+@@ -37,24 +37,42 @@ typedef unsigned long long uint64;
+ */
+ #if defined(__ppc__) || defined (__powerpc__)
+
+-#define READ_TIMESTAMP(var) ppc_getcounter(&var)
++#if defined( __powerpc64__) || defined(__LP64__)
++/* 64-bit PowerPC */
++#define READ_TIMESTAMP(var) ppc64_getcounter(&var)
++static void
++ppc64_getcounter(uint64 *v)
++{
++ /* On 64-bit PowerPC we can read the 64-bit timebase directly into a
++ 64-bit register */
++ uint64 timebase;
++#ifdef _ARCH_PWR4
++ asm volatile ("mfspr %0,268" : "=r" (timebase));
++#else
++ asm volatile ("mftb %0" : "=r" (timebase));
++#endif
++ *v = timebase;
++}
++
++#else
++/* 32-bit PowerPC */
++#define READ_TIMESTAMP(var) ppc32_getcounter(&var)
+
+ static void
+-ppc_getcounter(uint64 *v)
++ppc32_getcounter(uint64 *v)
+ {
+- register unsigned long tbu, tb, tbu2;
++ union { long long ll; long ii[2]; } u;
++ long tmp;
+
+ loop:
+- asm volatile ("mftbu %0" : "=r" (tbu) );
+- asm volatile ("mftb %0" : "=r" (tb) );
+- asm volatile ("mftbu %0" : "=r" (tbu2));
+- if (__builtin_expect(tbu != tbu2, 0)) goto loop;
+-
+- /* The slightly peculiar way of writing the next lines is
+- compiled better by GCC than any other way I tried. */
+- ((long*)(v))[0] = tbu;
+- ((long*)(v))[1] = tb;
++ asm volatile ("mftbu %0" : "=r" (u.ii[0]) );
++ asm volatile ("mftb %0" : "=r" (u.ii[1]) );
++ asm volatile ("mftbu %0" : "=r" (tmp));
++ if (__builtin_expect(u.ii[0] != tmp, 0)) goto loop;
++
++ *v = u.ll;
+ }
++#endif /* powerpc 32/64 bit */
+
+ #elif defined(__i386__)
+
--- /dev/null
+diff -up Python-2.7.2/Include/dictobject.h.add-debug-malloc-stats Python-2.7.2/Include/dictobject.h
+--- Python-2.7.2/Include/dictobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
++++ Python-2.7.2/Include/dictobject.h 2011-09-16 19:03:25.105821625 -0400
+@@ -150,6 +150,8 @@ PyAPI_FUNC(PyObject *) PyDict_GetItemStr
+ PyAPI_FUNC(int) PyDict_SetItemString(PyObject *dp, const char *key, PyObject *item);
+ PyAPI_FUNC(int) PyDict_DelItemString(PyObject *dp, const char *key);
+
++PyAPI_FUNC(void) _PyDict_DebugMallocStats(FILE *out);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-2.7.2/Include/floatobject.h.add-debug-malloc-stats Python-2.7.2/Include/floatobject.h
+--- Python-2.7.2/Include/floatobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
++++ Python-2.7.2/Include/floatobject.h 2011-09-16 19:03:25.106821625 -0400
+@@ -132,6 +132,7 @@ PyAPI_FUNC(PyObject *) _PyFloat_FormatAd
+ failure. Used in builtin_round in bltinmodule.c. */
+ PyAPI_FUNC(PyObject *) _Py_double_round(double x, int ndigits);
+
++PyAPI_FUNC(void) _PyFloat_DebugMallocStats(FILE* out);
+
+
+ #ifdef __cplusplus
+diff -up Python-2.7.2/Include/frameobject.h.add-debug-malloc-stats Python-2.7.2/Include/frameobject.h
+--- Python-2.7.2/Include/frameobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
++++ Python-2.7.2/Include/frameobject.h 2011-09-16 19:03:25.107821625 -0400
+@@ -80,6 +80,8 @@ PyAPI_FUNC(void) PyFrame_FastToLocals(Py
+
+ PyAPI_FUNC(int) PyFrame_ClearFreeList(void);
+
++PyAPI_FUNC(void) _PyFrame_DebugMallocStats(FILE *out);
++
+ /* Return the line of code the frame is currently executing. */
+ PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *);
+
+diff -up Python-2.7.2/Include/intobject.h.add-debug-malloc-stats Python-2.7.2/Include/intobject.h
+--- Python-2.7.2/Include/intobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
++++ Python-2.7.2/Include/intobject.h 2011-09-16 19:03:25.107821625 -0400
+@@ -74,6 +74,8 @@ PyAPI_FUNC(PyObject *) _PyInt_FormatAdva
+ char *format_spec,
+ Py_ssize_t format_spec_len);
+
++PyAPI_FUNC(void) _PyInt_DebugMallocStats(FILE *out);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-2.7.2/Include/listobject.h.add-debug-malloc-stats Python-2.7.2/Include/listobject.h
+--- Python-2.7.2/Include/listobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
++++ Python-2.7.2/Include/listobject.h 2011-09-16 19:03:25.107821625 -0400
+@@ -62,6 +62,8 @@ PyAPI_FUNC(PyObject *) _PyList_Extend(Py
+ #define PyList_SET_ITEM(op, i, v) (((PyListObject *)(op))->ob_item[i] = (v))
+ #define PyList_GET_SIZE(op) Py_SIZE(op)
+
++PyAPI_FUNC(void) _PyList_DebugMallocStats(FILE *out);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-2.7.2/Include/methodobject.h.add-debug-malloc-stats Python-2.7.2/Include/methodobject.h
+--- Python-2.7.2/Include/methodobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
++++ Python-2.7.2/Include/methodobject.h 2011-09-16 19:03:25.108821625 -0400
+@@ -87,6 +87,10 @@ typedef struct {
+
+ PyAPI_FUNC(int) PyCFunction_ClearFreeList(void);
+
++PyAPI_FUNC(void) _PyCFunction_DebugMallocStats(FILE *out);
++PyAPI_FUNC(void) _PyMethod_DebugMallocStats(FILE *out);
++
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-2.7.2/Include/object.h.add-debug-malloc-stats Python-2.7.2/Include/object.h
+--- Python-2.7.2/Include/object.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
++++ Python-2.7.2/Include/object.h 2011-09-16 19:03:25.108821625 -0400
+@@ -980,6 +980,13 @@ PyAPI_DATA(PyObject *) _PyTrash_delete_l
+ _PyTrash_thread_deposit_object((PyObject*)op); \
+ } while (0);
+
++PyAPI_FUNC(void)
++_PyDebugAllocatorStats(FILE *out, const char *block_name, int num_blocks,
++ size_t sizeof_block);
++
++PyAPI_FUNC(void)
++_PyObject_DebugTypeStats(FILE *out);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-2.7.2/Include/objimpl.h.add-debug-malloc-stats Python-2.7.2/Include/objimpl.h
+--- Python-2.7.2/Include/objimpl.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
++++ Python-2.7.2/Include/objimpl.h 2011-09-16 19:03:25.108821625 -0400
+@@ -101,13 +101,13 @@ PyAPI_FUNC(void) PyObject_Free(void *);
+
+ /* Macros */
+ #ifdef WITH_PYMALLOC
++PyAPI_FUNC(void) _PyObject_DebugMallocStats(FILE *out);
+ #ifdef PYMALLOC_DEBUG /* WITH_PYMALLOC && PYMALLOC_DEBUG */
+ PyAPI_FUNC(void *) _PyObject_DebugMalloc(size_t nbytes);
+ PyAPI_FUNC(void *) _PyObject_DebugRealloc(void *p, size_t nbytes);
+ PyAPI_FUNC(void) _PyObject_DebugFree(void *p);
+ PyAPI_FUNC(void) _PyObject_DebugDumpAddress(const void *p);
+ PyAPI_FUNC(void) _PyObject_DebugCheckAddress(const void *p);
+-PyAPI_FUNC(void) _PyObject_DebugMallocStats(void);
+ PyAPI_FUNC(void *) _PyObject_DebugMallocApi(char api, size_t nbytes);
+ PyAPI_FUNC(void *) _PyObject_DebugReallocApi(char api, void *p, size_t nbytes);
+ PyAPI_FUNC(void) _PyObject_DebugFreeApi(char api, void *p);
+diff -up Python-2.7.2/Include/stringobject.h.add-debug-malloc-stats Python-2.7.2/Include/stringobject.h
+--- Python-2.7.2/Include/stringobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
++++ Python-2.7.2/Include/stringobject.h 2011-09-16 19:03:25.109821625 -0400
+@@ -204,6 +204,8 @@ PyAPI_FUNC(PyObject *) _PyBytes_FormatAd
+ char *format_spec,
+ Py_ssize_t format_spec_len);
+
++PyAPI_FUNC(void) _PyString_DebugMallocStats(FILE *out);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-2.7.2/Include/unicodeobject.h.add-debug-malloc-stats Python-2.7.2/Include/unicodeobject.h
+--- Python-2.7.2/Include/unicodeobject.h.add-debug-malloc-stats 2011-06-11 11:46:23.000000000 -0400
++++ Python-2.7.2/Include/unicodeobject.h 2011-09-16 19:03:25.109821625 -0400
+@@ -1406,6 +1406,8 @@ PyAPI_FUNC(int) _PyUnicode_IsAlpha(
+ Py_UNICODE ch /* Unicode character */
+ );
+
++PyAPI_FUNC(void) _PyUnicode_DebugMallocStats(FILE *out);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-2.7.2/Lib/test/test_sys.py.add-debug-malloc-stats Python-2.7.2/Lib/test/test_sys.py
+--- Python-2.7.2/Lib/test/test_sys.py.add-debug-malloc-stats 2011-09-16 19:03:25.048821626 -0400
++++ Python-2.7.2/Lib/test/test_sys.py 2011-09-16 19:03:25.110821625 -0400
+@@ -473,6 +473,32 @@ class SysModuleTest(unittest.TestCase):
+ p.wait()
+ self.assertIn(executable, ["''", repr(sys.executable)])
+
++ def test_debugmallocstats(self):
++ # Test sys._debugmallocstats()
++
++ import subprocess
++
++ # Verify the default of writing to stderr:
++ p = subprocess.Popen([sys.executable,
++ '-c', 'import sys; sys._debugmallocstats()'],
++ stderr=subprocess.PIPE)
++ out, err = p.communicate()
++ p.wait()
++ self.assertIn("arenas allocated current", err)
++
++ # Verify that we can redirect the output to a file (not a file-like
++ # object, though):
++ with open('mallocstats.txt', 'w') as out:
++ sys._debugmallocstats(out)
++ result = open('mallocstats.txt').read()
++ self.assertIn("arenas allocated current", result)
++ os.unlink('mallocstats.txt')
++
++ # Verify that the destination must be a file:
++ with self.assertRaises(TypeError):
++ sys._debugmallocstats(42)
++
++
+ @test.test_support.cpython_only
+ class SizeofTest(unittest.TestCase):
+
+diff -up Python-2.7.2/Objects/classobject.c.add-debug-malloc-stats Python-2.7.2/Objects/classobject.c
+--- Python-2.7.2/Objects/classobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/classobject.c 2011-09-16 19:03:25.110821625 -0400
+@@ -2670,3 +2670,12 @@ PyMethod_Fini(void)
+ {
+ (void)PyMethod_ClearFreeList();
+ }
++
++/* Print summary info about the state of the optimized allocator */
++void
++_PyMethod_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out,
++ "free PyMethodObject",
++ numfree, sizeof(PyMethodObject));
++}
+diff -up Python-2.7.2/Objects/dictobject.c.add-debug-malloc-stats Python-2.7.2/Objects/dictobject.c
+--- Python-2.7.2/Objects/dictobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/dictobject.c 2011-09-16 19:03:25.111821625 -0400
+@@ -225,6 +225,15 @@ show_track(void)
+ static PyDictObject *free_list[PyDict_MAXFREELIST];
+ static int numfree = 0;
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PyDict_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out,
++ "free PyDictObject", numfree, sizeof(PyDictObject));
++}
++
++
+ void
+ PyDict_Fini(void)
+ {
+diff -up Python-2.7.2/Objects/floatobject.c.add-debug-malloc-stats Python-2.7.2/Objects/floatobject.c
+--- Python-2.7.2/Objects/floatobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/floatobject.c 2011-09-16 19:03:25.111821625 -0400
+@@ -35,6 +35,22 @@ typedef struct _floatblock PyFloatBlock;
+ static PyFloatBlock *block_list = NULL;
+ static PyFloatObject *free_list = NULL;
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PyFloat_DebugMallocStats(FILE *out)
++{
++ int num_blocks = 0;
++ PyFloatBlock *block;
++
++ /* Walk the block list, counting */
++ for (block = block_list; block ; block = block->next) {
++ num_blocks++;
++ }
++
++ _PyDebugAllocatorStats(out,
++ "PyFloatBlock", num_blocks, sizeof(PyFloatBlock));
++}
++
+ static PyFloatObject *
+ fill_free_list(void)
+ {
+diff -up Python-2.7.2/Objects/frameobject.c.add-debug-malloc-stats Python-2.7.2/Objects/frameobject.c
+--- Python-2.7.2/Objects/frameobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/frameobject.c 2011-09-16 19:03:25.112821625 -0400
+@@ -980,3 +980,13 @@ PyFrame_Fini(void)
+ Py_XDECREF(builtin_object);
+ builtin_object = NULL;
+ }
++
++/* Print summary info about the state of the optimized allocator */
++void
++_PyFrame_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out,
++ "free PyFrameObject",
++ numfree, sizeof(PyFrameObject));
++}
++
+diff -up Python-2.7.2/Objects/intobject.c.add-debug-malloc-stats Python-2.7.2/Objects/intobject.c
+--- Python-2.7.2/Objects/intobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/intobject.c 2011-09-16 19:03:25.112821625 -0400
+@@ -44,6 +44,23 @@ typedef struct _intblock PyIntBlock;
+ static PyIntBlock *block_list = NULL;
+ static PyIntObject *free_list = NULL;
+
++
++/* Print summary info about the state of the optimized allocator */
++void
++_PyInt_DebugMallocStats(FILE *out)
++{
++ int num_blocks = 0;
++ PyIntBlock *block;
++
++ /* Walk the block list, counting */
++ for (block = block_list; block ; block = block->next) {
++ num_blocks++;
++ }
++
++ _PyDebugAllocatorStats(out,
++ "PyIntBlock", num_blocks, sizeof(PyIntBlock));
++}
++
+ static PyIntObject *
+ fill_free_list(void)
+ {
+diff -up Python-2.7.2/Objects/listobject.c.add-debug-malloc-stats Python-2.7.2/Objects/listobject.c
+--- Python-2.7.2/Objects/listobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/listobject.c 2011-09-16 19:03:25.113821625 -0400
+@@ -109,6 +109,15 @@ PyList_Fini(void)
+ }
+ }
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PyList_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out,
++ "free PyListObject",
++ numfree, sizeof(PyListObject));
++}
++
+ PyObject *
+ PyList_New(Py_ssize_t size)
+ {
+diff -up Python-2.7.2/Objects/methodobject.c.add-debug-malloc-stats Python-2.7.2/Objects/methodobject.c
+--- Python-2.7.2/Objects/methodobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/methodobject.c 2011-09-16 19:03:25.113821625 -0400
+@@ -412,6 +412,15 @@ PyCFunction_Fini(void)
+ (void)PyCFunction_ClearFreeList();
+ }
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PyCFunction_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out,
++ "free PyCFunction",
++ numfree, sizeof(PyCFunction));
++}
++
+ /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
+ but it's part of the API so we need to keep a function around that
+ existing C extensions can call.
+diff -up Python-2.7.2/Objects/object.c.add-debug-malloc-stats Python-2.7.2/Objects/object.c
+--- Python-2.7.2/Objects/object.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/object.c 2011-09-16 19:04:46.463820849 -0400
+@@ -2334,6 +2334,23 @@ PyMem_Free(void *p)
+ PyMem_FREE(p);
+ }
+
++void
++_PyObject_DebugTypeStats(FILE *out)
++{
++ _PyString_DebugMallocStats(out);
++ _PyCFunction_DebugMallocStats(out);
++ _PyDict_DebugMallocStats(out);
++ _PyFloat_DebugMallocStats(out);
++ _PyFrame_DebugMallocStats(out);
++ _PyInt_DebugMallocStats(out);
++ _PyList_DebugMallocStats(out);
++ _PyMethod_DebugMallocStats(out);
++ _PySet_DebugMallocStats(out);
++ _PyTuple_DebugMallocStats(out);
++#if Py_USING_UNICODE
++ _PyUnicode_DebugMallocStats(out);
++#endif
++}
+
+ /* These methods are used to control infinite recursion in repr, str, print,
+ etc. Container objects that may recursively contain themselves,
+diff -up Python-2.7.2/Objects/obmalloc.c.add-debug-malloc-stats Python-2.7.2/Objects/obmalloc.c
+--- Python-2.7.2/Objects/obmalloc.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/obmalloc.c 2011-09-16 19:03:25.114821625 -0400
+@@ -508,12 +508,10 @@ static struct arena_object* usable_arena
+ /* Number of arenas allocated that haven't been free()'d. */
+ static size_t narenas_currently_allocated = 0;
+
+-#ifdef PYMALLOC_DEBUG
+ /* Total number of times malloc() called to allocate an arena. */
+ static size_t ntimes_arena_allocated = 0;
+ /* High water mark (max value ever seen) for narenas_currently_allocated. */
+ static size_t narenas_highwater = 0;
+-#endif
+
+ /* Allocate a new arena. If we run out of memory, return NULL. Else
+ * allocate a new arena, and return the address of an arena_object
+@@ -528,7 +526,7 @@ new_arena(void)
+
+ #ifdef PYMALLOC_DEBUG
+ if (Py_GETENV("PYTHONMALLOCSTATS"))
+- _PyObject_DebugMallocStats();
++ _PyObject_DebugMallocStats(stderr);
+ #endif
+ if (unused_arena_objects == NULL) {
+ uint i;
+@@ -588,11 +586,9 @@ new_arena(void)
+ arenaobj->address = (uptr)address;
+
+ ++narenas_currently_allocated;
+-#ifdef PYMALLOC_DEBUG
+ ++ntimes_arena_allocated;
+ if (narenas_currently_allocated > narenas_highwater)
+ narenas_highwater = narenas_currently_allocated;
+-#endif
+ arenaobj->freepools = NULL;
+ /* pool_address <- first pool-aligned address in the arena
+ nfreepools <- number of whole pools that fit after alignment */
+@@ -1694,17 +1690,19 @@ _PyObject_DebugDumpAddress(const void *p
+ }
+ }
+
++#endif /* PYMALLOC_DEBUG */
++
+ static size_t
+-printone(const char* msg, size_t value)
++printone(FILE *out, const char* msg, size_t value)
+ {
+ int i, k;
+ char buf[100];
+ size_t origvalue = value;
+
+- fputs(msg, stderr);
++ fputs(msg, out);
+ for (i = (int)strlen(msg); i < 35; ++i)
+- fputc(' ', stderr);
+- fputc('=', stderr);
++ fputc(' ', out);
++ fputc('=', out);
+
+ /* Write the value with commas. */
+ i = 22;
+@@ -1725,17 +1723,32 @@ printone(const char* msg, size_t value)
+
+ while (i >= 0)
+ buf[i--] = ' ';
+- fputs(buf, stderr);
++ fputs(buf, out);
+
+ return origvalue;
+ }
+
+-/* Print summary info to stderr about the state of pymalloc's structures.
++void
++_PyDebugAllocatorStats(FILE *out,
++ const char *block_name, int num_blocks, size_t sizeof_block)
++{
++ char buf1[128];
++ char buf2[128];
++ PyOS_snprintf(buf1, sizeof(buf1),
++ "%d %ss * %zd bytes each",
++ num_blocks, block_name, sizeof_block);
++ PyOS_snprintf(buf2, sizeof(buf2),
++ "%48s ", buf1);
++ (void)printone(out, buf2, num_blocks * sizeof_block);
++}
++
++
++/* Print summary info to "out" about the state of pymalloc's structures.
+ * In Py_DEBUG mode, also perform some expensive internal consistency
+ * checks.
+ */
+ void
+-_PyObject_DebugMallocStats(void)
++_PyObject_DebugMallocStats(FILE *out)
+ {
+ uint i;
+ const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT;
+@@ -1764,7 +1777,7 @@ _PyObject_DebugMallocStats(void)
+ size_t total;
+ char buf[128];
+
+- fprintf(stderr, "Small block threshold = %d, in %u size classes.\n",
++ fprintf(out, "Small block threshold = %d, in %u size classes.\n",
+ SMALL_REQUEST_THRESHOLD, numclasses);
+
+ for (i = 0; i < numclasses; ++i)
+@@ -1818,10 +1831,10 @@ _PyObject_DebugMallocStats(void)
+ }
+ assert(narenas == narenas_currently_allocated);
+
+- fputc('\n', stderr);
++ fputc('\n', out);
+ fputs("class size num pools blocks in use avail blocks\n"
+ "----- ---- --------- ------------- ------------\n",
+- stderr);
++ out);
+
+ for (i = 0; i < numclasses; ++i) {
+ size_t p = numpools[i];
+@@ -1832,7 +1845,7 @@ _PyObject_DebugMallocStats(void)
+ assert(b == 0 && f == 0);
+ continue;
+ }
+- fprintf(stderr, "%5u %6u "
++ fprintf(out, "%5u %6u "
+ "%11" PY_FORMAT_SIZE_T "u "
+ "%15" PY_FORMAT_SIZE_T "u "
+ "%13" PY_FORMAT_SIZE_T "u\n",
+@@ -1842,36 +1855,35 @@ _PyObject_DebugMallocStats(void)
+ pool_header_bytes += p * POOL_OVERHEAD;
+ quantization += p * ((POOL_SIZE - POOL_OVERHEAD) % size);
+ }
+- fputc('\n', stderr);
+- (void)printone("# times object malloc called", serialno);
+-
+- (void)printone("# arenas allocated total", ntimes_arena_allocated);
+- (void)printone("# arenas reclaimed", ntimes_arena_allocated - narenas);
+- (void)printone("# arenas highwater mark", narenas_highwater);
+- (void)printone("# arenas allocated current", narenas);
++ fputc('\n', out);
++#ifdef PYMALLOC_DEBUG
++ (void)printone(out, "# times object malloc called", serialno);
++#endif
++ (void)printone(out, "# arenas allocated total", ntimes_arena_allocated);
++ (void)printone(out, "# arenas reclaimed", ntimes_arena_allocated - narenas);
++ (void)printone(out, "# arenas highwater mark", narenas_highwater);
++ (void)printone(out, "# arenas allocated current", narenas);
+
+ PyOS_snprintf(buf, sizeof(buf),
+ "%" PY_FORMAT_SIZE_T "u arenas * %d bytes/arena",
+ narenas, ARENA_SIZE);
+- (void)printone(buf, narenas * ARENA_SIZE);
++ (void)printone(out, buf, narenas * ARENA_SIZE);
+
+- fputc('\n', stderr);
++ fputc('\n', out);
+
+- total = printone("# bytes in allocated blocks", allocated_bytes);
+- total += printone("# bytes in available blocks", available_bytes);
++ total = printone(out, "# bytes in allocated blocks", allocated_bytes);
++ total += printone(out, "# bytes in available blocks", available_bytes);
+
+ PyOS_snprintf(buf, sizeof(buf),
+ "%u unused pools * %d bytes", numfreepools, POOL_SIZE);
+- total += printone(buf, (size_t)numfreepools * POOL_SIZE);
++ total += printone(out, buf, (size_t)numfreepools * POOL_SIZE);
+
+- total += printone("# bytes lost to pool headers", pool_header_bytes);
+- total += printone("# bytes lost to quantization", quantization);
+- total += printone("# bytes lost to arena alignment", arena_alignment);
+- (void)printone("Total", total);
++ total += printone(out, "# bytes lost to pool headers", pool_header_bytes);
++ total += printone(out, "# bytes lost to quantization", quantization);
++ total += printone(out, "# bytes lost to arena alignment", arena_alignment);
++ (void)printone(out, "Total", total);
+ }
+
+-#endif /* PYMALLOC_DEBUG */
+-
+ #ifdef Py_USING_MEMORY_DEBUGGER
+ /* Make this function last so gcc won't inline it since the definition is
+ * after the reference.
+diff -up Python-2.7.2/Objects/setobject.c.add-debug-malloc-stats Python-2.7.2/Objects/setobject.c
+--- Python-2.7.2/Objects/setobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/setobject.c 2011-09-16 19:03:25.115821625 -0400
+@@ -1088,6 +1088,16 @@ PySet_Fini(void)
+ Py_CLEAR(emptyfrozenset);
+ }
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PySet_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out,
++ "free PySetObject",
++ numfree, sizeof(PySetObject));
++}
++
++
+ static PyObject *
+ set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+diff -up Python-2.7.2/Objects/stringobject.c.add-debug-malloc-stats Python-2.7.2/Objects/stringobject.c
+--- Python-2.7.2/Objects/stringobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/stringobject.c 2011-09-16 19:03:25.116821625 -0400
+@@ -4822,3 +4822,43 @@ void _Py_ReleaseInternedStrings(void)
+ PyDict_Clear(interned);
+ Py_CLEAR(interned);
+ }
++
++void _PyString_DebugMallocStats(FILE *out)
++{
++ ssize_t i;
++ int num_immortal = 0, num_mortal = 0;
++ ssize_t immortal_size = 0, mortal_size = 0;
++
++ if (interned == NULL || !PyDict_Check(interned))
++ return;
++
++ for (i = 0; i <= ((PyDictObject*)interned)->ma_mask; i++) {
++ PyDictEntry *ep = ((PyDictObject*)interned)->ma_table + i;
++ PyObject *pvalue = ep->me_value;
++ if (pvalue != NULL) {
++ PyStringObject *s = (PyStringObject *)ep->me_key;
++
++ switch (s->ob_sstate) {
++ case SSTATE_NOT_INTERNED:
++ /* XXX Shouldn't happen */
++ break;
++ case SSTATE_INTERNED_IMMORTAL:
++ num_immortal ++;
++ immortal_size += s->ob_size;
++ break;
++ case SSTATE_INTERNED_MORTAL:
++ num_mortal ++;
++ mortal_size += s->ob_size;
++ break;
++ default:
++ Py_FatalError("Inconsistent interned string state.");
++ }
++ }
++ }
++
++ fprintf(out, "%d mortal interned strings\n", num_mortal);
++ fprintf(out, "%d immortal interned strings\n", num_immortal);
++ fprintf(out, "total size of all interned strings: "
++ "%zi/%zi "
++ "mortal/immortal\n", mortal_size, immortal_size);
++}
+diff -up Python-2.7.2/Objects/tupleobject.c.add-debug-malloc-stats Python-2.7.2/Objects/tupleobject.c
+--- Python-2.7.2/Objects/tupleobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/tupleobject.c 2011-09-16 19:03:25.116821625 -0400
+@@ -44,6 +44,22 @@ show_track(void)
+ }
+ #endif
+
++/* Print summary info about the state of the optimized allocator */
++void
++_PyTuple_DebugMallocStats(FILE *out)
++{
++#if PyTuple_MAXSAVESIZE > 0
++ int i;
++ char buf[128];
++ for (i = 1; i < PyTuple_MAXSAVESIZE; i++) {
++ PyOS_snprintf(buf, sizeof(buf),
++ "free %d-sized PyTupleObject", i);
++ _PyDebugAllocatorStats(out,
++ buf,
++ numfree[i], _PyObject_VAR_SIZE(&PyTuple_Type, i));
++ }
++#endif
++}
+
+ PyObject *
+ PyTuple_New(register Py_ssize_t size)
+diff -up Python-2.7.2/Objects/unicodeobject.c.add-debug-malloc-stats Python-2.7.2/Objects/unicodeobject.c
+--- Python-2.7.2/Objects/unicodeobject.c.add-debug-malloc-stats 2011-06-11 11:46:27.000000000 -0400
++++ Python-2.7.2/Objects/unicodeobject.c 2011-09-16 19:03:25.118821625 -0400
+@@ -8883,6 +8883,12 @@ _PyUnicode_Fini(void)
+ (void)PyUnicode_ClearFreeList();
+ }
+
++void _PyUnicode_DebugMallocStats(FILE *out)
++{
++ _PyDebugAllocatorStats(out, "free PyUnicodeObject", numfree,
++ sizeof(PyUnicodeObject));
++}
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff -up Python-2.7.2/Python/pythonrun.c.add-debug-malloc-stats Python-2.7.2/Python/pythonrun.c
+--- Python-2.7.2/Python/pythonrun.c.add-debug-malloc-stats 2011-09-16 19:03:25.025821626 -0400
++++ Python-2.7.2/Python/pythonrun.c 2011-09-16 19:03:25.118821625 -0400
+@@ -549,7 +549,7 @@ Py_Finalize(void)
+ #endif /* Py_TRACE_REFS */
+ #ifdef PYMALLOC_DEBUG
+ if (Py_GETENV("PYTHONMALLOCSTATS"))
+- _PyObject_DebugMallocStats();
++ _PyObject_DebugMallocStats(stderr);
+ #endif
+
+ call_ll_exitfuncs();
+diff -up Python-2.7.2/Python/sysmodule.c.add-debug-malloc-stats Python-2.7.2/Python/sysmodule.c
+--- Python-2.7.2/Python/sysmodule.c.add-debug-malloc-stats 2011-09-16 19:03:25.007821626 -0400
++++ Python-2.7.2/Python/sysmodule.c 2011-09-16 19:03:25.119821625 -0400
+@@ -872,6 +872,57 @@ a 11-tuple where the entries in the tupl
+ extern "C" {
+ #endif
+
++static PyObject *
++sys_debugmallocstats(PyObject *self, PyObject *args)
++{
++ PyObject *file = NULL;
++ FILE *fp;
++
++ if (!PyArg_ParseTuple(args, "|O!",
++ &PyFile_Type, &file)) {
++ return NULL;
++ }
++ if (!file) {
++ /* Default to sys.stderr: */
++ file = PySys_GetObject("stderr");
++ if (!file) {
++ PyErr_SetString(PyExc_ValueError, "sys.stderr not set");
++ return NULL;
++ }
++ if (!PyFile_Check(file)) {
++ PyErr_SetString(PyExc_TypeError, "sys.stderr is not a file");
++ return NULL;
++ }
++ }
++
++ Py_INCREF(file);
++ /* OK, we now own a ref on non-NULL "file" */
++
++ fp = PyFile_AsFile(file);
++ if (!fp) {
++ PyErr_SetString(PyExc_ValueError, "file is closed");
++ Py_DECREF(file);
++ return NULL;
++ }
++
++ _PyObject_DebugMallocStats(fp);
++ fputc('\n', fp);
++ _PyObject_DebugTypeStats(fp);
++
++ Py_DECREF(file);
++
++ Py_RETURN_NONE;
++}
++PyDoc_STRVAR(debugmallocstats_doc,
++"_debugmallocstats([file])\n\
++\n\
++Print summary info to the given file (or sys.stderr) about the state of\n\
++pymalloc's structures.\n\
++\n\
++In Py_DEBUG mode, also perform some expensive internal consistency\n\
++checks.\n\
++");
++
+ #ifdef Py_TRACE_REFS
+ /* Defined in objects.c because it uses static globals if that file */
+ extern PyObject *_Py_GetObjects(PyObject *, PyObject *);
+@@ -970,6 +1021,8 @@ static PyMethodDef sys_methods[] = {
+ {"settrace", sys_settrace, METH_O, settrace_doc},
+ {"gettrace", sys_gettrace, METH_NOARGS, gettrace_doc},
+ {"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc},
++ {"_debugmallocstats", sys_debugmallocstats, METH_VARARGS,
++ debugmallocstats_doc},
+ {NULL, NULL} /* sentinel */
+ };
+
--- /dev/null
+diff -up Python-2.7.3/Lib/test/test_gdb.py.gdb-autoload-safepath Python-2.7.3/Lib/test/test_gdb.py
+--- Python-2.7.3/Lib/test/test_gdb.py.gdb-autoload-safepath 2012-04-30 15:53:57.254045220 -0400
++++ Python-2.7.3/Lib/test/test_gdb.py 2012-04-30 16:19:19.569941124 -0400
+@@ -54,6 +54,19 @@ def gdb_has_frame_select():
+
+ HAS_PYUP_PYDOWN = gdb_has_frame_select()
+
++def gdb_has_autoload_safepath():
++ # Recent GDBs will only auto-load scripts from certain safe
++ # locations, so we will need to turn off this protection.
++ # However, if the GDB doesn't have it, then the following
++ # command will generate noise on stderr (rhbz#817072):
++ cmd = "--eval-command=set auto-load safe-path /"
++ p = subprocess.Popen(["gdb", "--batch", cmd],
++ stderr=subprocess.PIPE)
++ _, stderr = p.communicate()
++ return '"on" or "off" expected.' not in stderr
++
++HAS_AUTOLOAD_SAFEPATH = gdb_has_autoload_safepath()
++
+ class DebuggerTests(unittest.TestCase):
+
+ """Test that the debugger can debug Python."""
+diff -up Python-2.7.10/Lib/test/test_gdb.py.ms Python-2.7.10/Lib/test/test_gdb.py
+--- Python-2.7.10/Lib/test/test_gdb.py.ms 2015-05-25 17:00:25.028462615 +0200
++++ Python-2.7.10/Lib/test/test_gdb.py 2015-05-25 17:01:53.166359822 +0200
+@@ -153,6 +153,17 @@ class DebuggerTests(unittest.TestCase):
+
+ 'run']
+
++ if HAS_AUTOLOAD_SAFEPATH:
++ # Recent GDBs will only auto-load scripts from certain safe
++ # locations.
++ # Where necessary, turn off this protection to ensure that
++ # our -gdb.py script can be loaded - but not on earlier gdb builds
++ # as this would generate noise on stderr (rhbz#817072):
++ init_commands = ['set auto-load safe-path /']
++ else:
++ init_commands = []
++
++
+ # GDB as of 7.4 onwards can distinguish between the
+ # value of a variable at entry vs current value:
+ # http://sourceware.org/gdb/onlinedocs/gdb/Variables.html
+@@ -167,10 +178,11 @@ class DebuggerTests(unittest.TestCase):
+ else:
+ commands += ['backtrace']
+
+- # print commands
++ # print init_commands
+
+ # Use "commands" to generate the arguments with which to invoke "gdb":
+ args = ["gdb", "--batch", "-nx"]
++ args += ['--init-eval-command=%s' % cmd for cmd in init_commands]
+ args += ['--eval-command=%s' % cmd for cmd in commands]
+ args += ["--args",
+ sys.executable]
--- /dev/null
+diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py
+index 3354b34..10ba0e5 100644
+--- a/Lib/test/test_gdb.py
++++ b/Lib/test/test_gdb.py
+@@ -725,11 +725,10 @@ class PyListTests(DebuggerTests):
+ ' 2 \n'
+ ' 3 def foo(a, b, c):\n',
+ bt)
+-
++@unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
++@unittest.skipIf(python_is_optimized(),
++ "Python was compiled with optimizations")
+ class StackNavigationTests(DebuggerTests):
+- @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
+- @unittest.skipIf(python_is_optimized(),
+- "Python was compiled with optimizations")
+ def test_pyup_command(self):
+ 'Verify that the "py-up" command works'
+ bt = self.get_stack_trace(script=self.get_sample_script(),
+@@ -740,7 +739,6 @@ class StackNavigationTests(DebuggerTests):
+ baz\(a, b, c\)
+ $''')
+
+- @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
+ def test_down_at_bottom(self):
+ 'Verify handling of "py-down" at the bottom of the stack'
+ bt = self.get_stack_trace(script=self.get_sample_script(),
+@@ -748,9 +746,6 @@ $''')
+ self.assertEndsWith(bt,
+ 'Unable to find a newer python frame\n')
+
+- @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
+- @unittest.skipIf(python_is_optimized(),
+- "Python was compiled with optimizations")
+ def test_up_at_top(self):
+ 'Verify handling of "py-up" at the top of the stack'
+ bt = self.get_stack_trace(script=self.get_sample_script(),
+@@ -758,9 +753,6 @@ $''')
+ self.assertEndsWith(bt,
+ 'Unable to find an older python frame\n')
+
+- @unittest.skipUnless(HAS_PYUP_PYDOWN, "test requires py-up/py-down commands")
+- @unittest.skipIf(python_is_optimized(),
+- "Python was compiled with optimizations")
+ def test_up_then_down(self):
+ 'Verify "py-up" followed by "py-down"'
+ bt = self.get_stack_trace(script=self.get_sample_script(),
-diff -up Python-2.7.3/Lib/test/test_gc.py.gc-assertions Python-2.7.3/Lib/test/test_gc.py
---- Python-2.7.3/Lib/test/test_gc.py.gc-assertions 2013-02-20 16:28:20.890536607 -0500
-+++ Python-2.7.3/Lib/test/test_gc.py 2013-02-20 16:39:52.720489297 -0500
-@@ -1,6 +1,7 @@
+diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py
+index 7e47b2d..12a210d 100644
+--- a/Lib/test/test_gc.py
++++ b/Lib/test/test_gc.py
+@@ -1,7 +1,8 @@
import unittest
--from test.test_support import verbose, run_unittest, start_threads
-+from test.test_support import verbose, run_unittest, start_threads, import_module
+ from test.support import (verbose, run_unittest, start_threads,
+- requires_type_collecting)
++ requires_type_collecting, import_module)
import sys
+import sysconfig
import time
import gc
import weakref
-@@ -32,6 +33,8 @@ class GC_Detector(object):
+@@ -39,6 +40,8 @@ class GC_Detector(object):
self.wr = weakref.ref(C1055820(666), it_happened)
### Tests
###############################################################################
-@@ -476,6 +479,49 @@ class GCTests(unittest.TestCase):
+@@ -537,6 +540,49 @@ class GCTests(unittest.TestCase):
# would be damaged, with an empty __dict__.
self.assertEqual(x, None)
class GCTogglingTests(unittest.TestCase):
def setUp(self):
gc.enable()
-diff -up Python-2.7.3/Modules/gcmodule.c.gc-assertions Python-2.7.3/Modules/gcmodule.c
---- Python-2.7.3/Modules/gcmodule.c.gc-assertions 2012-04-09 19:07:34.000000000 -0400
-+++ Python-2.7.3/Modules/gcmodule.c 2013-02-20 16:28:21.029536600 -0500
+diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
+index 916e481..0233ce2 100644
+--- a/Modules/gcmodule.c
++++ b/Modules/gcmodule.c
@@ -21,6 +21,73 @@
#include "Python.h"
#include "frameobject.h" /* for PyFrame_ClearFreeList */
/* Get an object's GC head */
#define AS_GC(o) ((PyGC_Head *)(o)-1)
-@@ -288,7 +355,8 @@ update_refs(PyGC_Head *containers)
+@@ -328,7 +395,8 @@ update_refs(PyGC_Head *containers)
{
PyGC_Head *gc = containers->gc.gc_next;
for (; gc != containers; gc = gc->gc.gc_next) {
gc->gc.gc_refs = Py_REFCNT(FROM_GC(gc));
/* Python's cyclic gc should never see an incoming refcount
* of 0: if something decref'ed to 0, it should have been
-@@ -308,7 +376,8 @@ update_refs(PyGC_Head *containers)
+@@ -348,7 +416,8 @@ update_refs(PyGC_Head *containers)
* so serious that maybe this should be a release-build
* check instead of an assert?
*/
}
}
-@@ -323,7 +392,9 @@ visit_decref(PyObject *op, void *data)
+@@ -363,7 +432,9 @@ visit_decref(PyObject *op, void *data)
* generation being collected, which can be recognized
* because only they have positive gc_refs.
*/
if (gc->gc.gc_refs > 0)
gc->gc.gc_refs--;
}
-@@ -383,9 +454,10 @@ visit_reachable(PyObject *op, PyGC_Head
+@@ -423,9 +494,10 @@ visit_reachable(PyObject *op, PyGC_Head *reachable)
* If gc_refs == GC_UNTRACKED, it must be ignored.
*/
else {
}
}
return 0;
-@@ -427,7 +499,7 @@ move_unreachable(PyGC_Head *young, PyGC_
+@@ -467,7 +539,7 @@ move_unreachable(PyGC_Head *young, PyGC_Head *unreachable)
*/
PyObject *op = FROM_GC(gc);
traverseproc traverse = Py_TYPE(op)->tp_traverse;
gc->gc.gc_refs = GC_REACHABLE;
(void) traverse(op,
(visitproc)visit_reachable,
-@@ -494,7 +566,8 @@ move_finalizers(PyGC_Head *unreachable,
+@@ -545,7 +617,8 @@ move_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers)
for (gc = unreachable->gc.gc_next; gc != unreachable; gc = next) {
PyObject *op = FROM_GC(gc);
next = gc->gc.gc_next;
if (has_finalizer(op)) {
-@@ -570,7 +643,7 @@ handle_weakrefs(PyGC_Head *unreachable,
+@@ -621,7 +694,7 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
PyWeakReference **wrlist;
op = FROM_GC(gc);
next = gc->gc.gc_next;
if (! PyType_SUPPORTS_WEAKREFS(Py_TYPE(op)))
-@@ -591,9 +664,9 @@ handle_weakrefs(PyGC_Head *unreachable,
+@@ -642,9 +715,9 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
* the callback pointer intact. Obscure: it also
* changes *wrlist.
*/
if (wr->wr_callback == NULL)
continue; /* no callback */
-@@ -627,7 +700,7 @@ handle_weakrefs(PyGC_Head *unreachable,
+@@ -678,7 +751,7 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
*/
if (IS_TENTATIVELY_UNREACHABLE(wr))
continue;
/* Create a new reference so that wr can't go away
* before we can process it again.
-@@ -636,7 +709,8 @@ handle_weakrefs(PyGC_Head *unreachable,
+@@ -687,7 +760,8 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
/* Move wr to wrcb_to_call, for the next pass. */
wrasgc = AS_GC(wr);
next isn't, so they can't
be the same */
gc_list_move(wrasgc, &wrcb_to_call);
-@@ -652,11 +726,11 @@ handle_weakrefs(PyGC_Head *unreachable,
+@@ -703,11 +777,11 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
gc = wrcb_to_call.gc.gc_next;
op = FROM_GC(gc);
/* copy-paste of weakrefobject.c's handle_callback() */
temp = PyObject_CallFunctionObjArgs(callback, wr, NULL);
-@@ -759,7 +833,7 @@ delete_garbage(PyGC_Head *collectable, P
+@@ -810,7 +884,7 @@ delete_garbage(PyGC_Head *collectable, PyGC_Head *old)
PyGC_Head *gc = collectable->gc.gc_next;
PyObject *op = FROM_GC(gc);
+++ /dev/null
-diff -up Python-2.7.3/Lib/test/test_support.py.rhbz913732 Python-2.7.3/Lib/test/test_support.py
---- Python-2.7.3/Lib/test/test_support.py.rhbz913732 2013-03-04 16:11:53.757315921 -0500
-+++ Python-2.7.3/Lib/test/test_support.py 2013-03-04 16:12:11.331314722 -0500
-@@ -304,7 +304,8 @@ def bind_port(sock, host=HOST):
- if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) == 1:
- raise TestFailed("tests should never set the SO_REUSEADDR " \
- "socket option on TCP/IP sockets!")
-- if hasattr(socket, 'SO_REUSEPORT'):
-+ if hasattr(socket, 'SO_REUSEPORT') \
-+ and 'WITHIN_PYTHON_RPM_BUILD' not in os.environ: # rhbz#913732
- try:
- if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT) == 1:
- raise TestFailed("tests should never set the SO_REUSEPORT " \
- "socket option on TCP/IP sockets!")
--- /dev/null
+diff --git a/config.sub b/config.sub
+index 3478c1f..e422173 100755
+--- a/config.sub
++++ b/config.sub
+@@ -1040,7 +1040,7 @@ case $basic_machine in
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
++ ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little)
+ basic_machine=powerpc64le-unknown
if not gotit:
if __debug__:
@@ -599,7 +602,7 @@ class _Event(_Verbose):
- finally:
- self.__cond.release()
+ with self.__cond:
+ self.__flag = False
- def wait(self, timeout=None):
+ def wait(self, timeout=None, balancing=True):
If the internal flag is true on entry, return immediately. Otherwise,
@@ -617,7 +620,7 @@ class _Event(_Verbose):
- self.__cond.acquire()
- try:
+ """
+ with self.__cond:
if not self.__flag:
- self.__cond.wait(timeout)
+ self.__cond.wait(timeout, balancing)
return self.__flag
- finally:
- self.__cond.release()
+
+ # Helper to generate new thread names
@@ -908,7 +911,7 @@ class Thread(_Verbose):
if 'dummy_threading' not in _sys.modules:
raise
+++ /dev/null
---- Python-3.3.2/setup.py.orig 2013-07-01 15:23:24.377711044 +0200
-+++ Python-3.3.2/setup.py 2013-07-01 15:23:34.094676496 +0200
-@@ -1882,7 +1882,8 @@
- if not line:
- ffi_inc = None
- break
-- if line.startswith('#define LIBFFI_H'):
-+ if line.startswith('#define LIBFFI_H') or \
-+ line.startswith('#define ffi_wrapper_h'):
- break
- ffi_lib = None
- if ffi_inc is not None:
--- /dev/null
+diff -r e8b8279ca118 setup.py
+--- a/setup.py Sun Jul 21 21:57:52 2013 -0400
++++ b/setup.py Tue Aug 20 09:45:31 2013 +0200
+@@ -1480,12 +1480,21 @@
+ 'expat/xmltok_impl.h'
+ ]
+
++ # Add an explicit RPATH to pyexpat.so pointing at the directory
++ # containing the system expat (which has the extra XML_SetHashSalt
++ # symbol), to avoid an ImportError with a link error if there's an
++ # LD_LIBRARY_PATH containing a "vanilla" build of expat (without the
++ # symbol) (rhbz#833271):
++ EXPAT_RPATH = '/usr/lib64' if sys.maxint == 0x7fffffffffffffff else '/usr/lib'
++
++
+ exts.append(Extension('pyexpat',
+ define_macros = define_macros,
+ include_dirs = expat_inc,
+ libraries = expat_lib,
+ sources = ['pyexpat.c'] + expat_sources,
+ depends = expat_depends,
++ extra_link_args = ['-Wl,-rpath,%s' % EXPAT_RPATH]
+ ))
+
+ # Fredrik Lundh's cElementTree module. Note that this also
--- /dev/null
+diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py
+index 89ed1ef..8008222 100644
+--- a/Lib/ensurepip/__init__.py
++++ b/Lib/ensurepip/__init__.py
+@@ -1,9 +1,10 @@
+ #!/usr/bin/env python2
+ from __future__ import print_function
+
++import distutils.version
++import glob
+ import os
+ import os.path
+-import pkgutil
+ import shutil
+ import sys
+ import tempfile
+@@ -11,10 +12,20 @@ import tempfile
+
+ __all__ = ["version", "bootstrap"]
+
++_WHEEL_DIR = "/usr/share/python-wheels/"
+
+-_SETUPTOOLS_VERSION = "39.0.1"
+
+-_PIP_VERSION = "9.0.3"
++def _get_most_recent_wheel_version(pkg):
++ prefix = os.path.join(_WHEEL_DIR, "{}-".format(pkg))
++ suffix = "-py2.py3-none-any.whl"
++ pattern = "{}*{}".format(prefix, suffix)
++ versions = (p[len(prefix):-len(suffix)] for p in glob.glob(pattern))
++ return str(max(versions, key=distutils.version.LooseVersion))
++
++
++_SETUPTOOLS_VERSION = _get_most_recent_wheel_version("setuptools")
++
++_PIP_VERSION = _get_most_recent_wheel_version("pip")
+
+ _PROJECTS = [
+ ("setuptools", _SETUPTOOLS_VERSION),
+@@ -28,8 +39,13 @@ def _run_pip(args, additional_paths=None):
+ sys.path = additional_paths + sys.path
+
+ # Install the bundled software
+- import pip
+- return pip.main(args)
++ try:
++ # pip 10
++ from pip._internal import main
++ except ImportError:
++ # pip 9
++ from pip import main
++ return main(args)
+
+
+ def version():
+@@ -100,12 +116,9 @@ def _bootstrap(root=None, upgrade=False, user=False,
+ additional_paths = []
+ for project, version in _PROJECTS:
+ wheel_name = "{}-{}-py2.py3-none-any.whl".format(project, version)
+- whl = pkgutil.get_data(
+- "ensurepip",
+- "_bundled/{}".format(wheel_name),
+- )
+- with open(os.path.join(tmpdir, wheel_name), "wb") as fp:
+- fp.write(whl)
++ with open(os.path.join(_WHEEL_DIR, wheel_name), "rb") as sfp:
++ with open(os.path.join(tmpdir, wheel_name), "wb") as fp:
++ fp.write(sfp.read())
+
+ additional_paths.append(os.path.join(tmpdir, wheel_name))
+
--- /dev/null
+--- Python-2.7.5-orig/Tools/gdb/libpython.py 2013-05-12 03:32:54.000000000 +0000
++++ Python-2.7.5-orig/Tools/gdb/libpython.py 2013-09-15 09:56:25.494000000 +0000
+@@ -887,6 +887,8 @@
+ newline character'''
+ if self.is_optimized_out():
+ return '(frame information optimized out)'
++ if self.filename() == '<string>':
++ return '(in an eval block)'
+ filename = self.filename()
+ try:
+ f = open(filename, 'r')
--- /dev/null
+diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py
+index 1bb6690..28ed25d 100644
+--- a/Lib/test/test_smtplib.py
++++ b/Lib/test/test_smtplib.py
+@@ -182,6 +182,7 @@ class DebuggingServerTests(unittest.TestCase):
+ smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15)
+ smtp.quit()
+
++ @unittest._skipInRpmBuild("Does not work in network-free environment")
+ def testNOOP(self):
+ smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=15)
+ expected = (250, 'Ok')
--- /dev/null
+--- Python-2.7.5/setup.py.orig 2013-05-11 20:32:54.000000000 -0700
++++ Python-2.7.5/setup.py 2014-02-18 14:16:07.999004901 -0800
+@@ -1168,7 +1168,7 @@ class PyBuildExt(build_ext):
+ sqlite_defines.append(('MODULE_NAME', '\\"sqlite3\\"'))
+
+ # Comment this out if you want the sqlite3 module to be able to load extensions.
+- sqlite_defines.append(("SQLITE_OMIT_LOAD_EXTENSION", "1"))
++ #sqlite_defines.append(("SQLITE_OMIT_LOAD_EXTENSION", "1"))
+
+ if host_platform == 'darwin':
+ # In every directory on the search path search for a dynamic
--- /dev/null
+diff --git a/setup.py b/setup.py
+index 585e380..9993f11 100644
+--- a/setup.py
++++ b/setup.py
+@@ -1346,11 +1346,7 @@ class PyBuildExt(build_ext):
+ else:
+ missing.append('resource')
+
+- nis = self._detect_nis(inc_dirs, lib_dirs)
+- if nis is not None:
+- exts.append(nis)
+- else:
+- missing.append('nis')
++ # nis (Sun yellow pages) is handled in Setup.dist
+
+ # Curses support, requiring the System V version of curses, often
+ # provided by the ncurses library.
+@@ -2162,51 +2158,6 @@ class PyBuildExt(build_ext):
+ # for dlopen, see bpo-32647
+ ext.libraries.append('dl')
+
+- def _detect_nis(self, inc_dirs, lib_dirs):
+- if host_platform in {'win32', 'cygwin', 'qnx6'}:
+- return None
+-
+- libs = []
+- library_dirs = []
+- includes_dirs = []
+-
+- # bpo-32521: glibc has deprecated Sun RPC for some time. Fedora 28
+- # moved headers and libraries to libtirpc and libnsl. The headers
+- # are in tircp and nsl sub directories.
+- rpcsvc_inc = find_file(
+- 'rpcsvc/yp_prot.h', inc_dirs,
+- [os.path.join(inc_dir, 'nsl') for inc_dir in inc_dirs]
+- )
+- rpc_inc = find_file(
+- 'rpc/rpc.h', inc_dirs,
+- [os.path.join(inc_dir, 'tirpc') for inc_dir in inc_dirs]
+- )
+- if rpcsvc_inc is None or rpc_inc is None:
+- # not found
+- return None
+- includes_dirs.extend(rpcsvc_inc)
+- includes_dirs.extend(rpc_inc)
+-
+- if self.compiler.find_library_file(lib_dirs, 'nsl'):
+- libs.append('nsl')
+- else:
+- # libnsl-devel: check for libnsl in nsl/ subdirectory
+- nsl_dirs = [os.path.join(lib_dir, 'nsl') for lib_dir in lib_dirs]
+- libnsl = self.compiler.find_library_file(nsl_dirs, 'nsl')
+- if libnsl is not None:
+- library_dirs.append(os.path.dirname(libnsl))
+- libs.append('nsl')
+-
+- if self.compiler.find_library_file(lib_dirs, 'tirpc'):
+- libs.append('tirpc')
+-
+- return Extension(
+- 'nis', ['nismodule.c'],
+- libraries=libs,
+- library_dirs=library_dirs,
+- include_dirs=includes_dirs
+- )
+-
+
+ class PyBuildInstall(install):
+ # Suppress the warning about installation into the lib_dynload
--- /dev/null
+From add531a1e55b0a739b0f42582f1c9747e5649ace Mon Sep 17 00:00:00 2001
+From: Benjamin Peterson <benjamin@python.org>
+Date: Tue, 28 Aug 2018 22:12:56 -0700
+Subject: [PATCH] closes bpo-34540: Convert shutil._call_external_zip to use
+ subprocess rather than distutils.spawn.
+
+---
+ Lib/shutil.py | 16 ++++++++++------
+ .../2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst | 3 +++
+ 2 files changed, 13 insertions(+), 6 deletions(-)
+ create mode 100644 Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst
+
+diff --git a/Lib/shutil.py b/Lib/shutil.py
+index 3462f7c5e91c..0ab1a06f5260 100644
+--- a/Lib/shutil.py
++++ b/Lib/shutil.py
+@@ -413,17 +413,21 @@ def _set_uid_gid(tarinfo):
+
+ return archive_name
+
+-def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False):
++def _call_external_zip(base_dir, zip_filename, verbose, dry_run, logger):
+ # XXX see if we want to keep an external call here
+ if verbose:
+ zipoptions = "-r"
+ else:
+ zipoptions = "-rq"
+- from distutils.errors import DistutilsExecError
+- from distutils.spawn import spawn
++ cmd = ["zip", zipoptions, zip_filename, base_dir]
++ if logger is not None:
++ logger.info(' '.join(cmd))
++ if dry_run:
++ return
++ import subprocess
+ try:
+- spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run)
+- except DistutilsExecError:
++ subprocess.check_call(cmd)
++ except subprocess.CalledProcessError:
+ # XXX really should distinguish between "couldn't find
+ # external 'zip' command" and "zip failed".
+ raise ExecError, \
+@@ -458,7 +462,7 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
+ zipfile = None
+
+ if zipfile is None:
+- _call_external_zip(base_dir, zip_filename, verbose, dry_run)
++ _call_external_zip(base_dir, zip_filename, verbose, dry_run, logger)
+ else:
+ if logger is not None:
+ logger.info("creating '%s' and adding '%s' to it",
+diff --git a/Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst b/Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst
+new file mode 100644
+index 000000000000..4f686962a87b
+--- /dev/null
++++ b/Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst
+@@ -0,0 +1,3 @@
++When ``shutil.make_archive`` falls back to the external ``zip`` problem, it
++uses :mod:`subprocess` to invoke it rather than :mod:`distutils.spawn`. This
++closes a possible shell injection vector.
--- /dev/null
+From 554c48934c599b3fb04c73d740bba1a745b89b41 Mon Sep 17 00:00:00 2001
+From: Christian Heimes <christian@python.org>
+Date: Tue, 18 Sep 2018 14:38:58 +0200
+Subject: [PATCH] [2.7] bpo-34623: Use XML_SetHashSalt in _elementtree
+ (GH-9146)
+
+The C accelerated _elementtree module now initializes hash randomization
+salt from _Py_HashSecret instead of libexpat's default CPRNG.
+
+Signed-off-by: Christian Heimes <christian@python.org>
+
+https://bugs.python.org/issue34623.
+(cherry picked from commit cb5778f00ce48631c7140f33ba242496aaf7102b)
+
+Co-authored-by: Christian Heimes <christian@python.org>
+---
+ Include/pyexpat.h | 4 +++-
+ .../next/Security/2018-09-10-16-05-39.bpo-34623.Ua9jMv.rst | 2 ++
+ Modules/_elementtree.c | 5 +++++
+ Modules/pyexpat.c | 5 +++++
+ 4 files changed, 15 insertions(+), 1 deletion(-)
+ create mode 100644 Misc/NEWS.d/next/Security/2018-09-10-16-05-39.bpo-34623.Ua9jMv.rst
+
+diff --git a/Include/pyexpat.h b/Include/pyexpat.h
+index 5340ef5fa386..3fc5fa54da63 100644
+--- a/Include/pyexpat.h
++++ b/Include/pyexpat.h
+@@ -3,7 +3,7 @@
+
+ /* note: you must import expat.h before importing this module! */
+
+-#define PyExpat_CAPI_MAGIC "pyexpat.expat_CAPI 1.0"
++#define PyExpat_CAPI_MAGIC "pyexpat.expat_CAPI 1.1"
+ #define PyExpat_CAPSULE_NAME "pyexpat.expat_CAPI"
+
+ struct PyExpat_CAPI
+@@ -43,6 +43,8 @@ struct PyExpat_CAPI
+ XML_Parser parser, XML_UnknownEncodingHandler handler,
+ void *encodingHandlerData);
+ void (*SetUserData)(XML_Parser parser, void *userData);
++ /* might be none for expat < 2.1.0 */
++ int (*SetHashSalt)(XML_Parser parser, unsigned long hash_salt);
+ /* always add new stuff to the end! */
+ };
+
+diff --git a/Misc/NEWS.d/next/Security/2018-09-10-16-05-39.bpo-34623.Ua9jMv.rst b/Misc/NEWS.d/next/Security/2018-09-10-16-05-39.bpo-34623.Ua9jMv.rst
+new file mode 100644
+index 000000000000..31ad92ef8582
+--- /dev/null
++++ b/Misc/NEWS.d/next/Security/2018-09-10-16-05-39.bpo-34623.Ua9jMv.rst
+@@ -0,0 +1,2 @@
++The C accelerated _elementtree module now initializes hash randomization
++salt from _Py_HashSecret instead of libexpat's default CSPRNG.
+diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
+index f7f992dd3a95..b38e0ab329c7 100644
+--- a/Modules/_elementtree.c
++++ b/Modules/_elementtree.c
+@@ -2574,6 +2574,11 @@ xmlparser(PyObject* self_, PyObject* args, PyObject* kw)
+ PyErr_NoMemory();
+ return NULL;
+ }
++ /* expat < 2.1.0 has no XML_SetHashSalt() */
++ if (EXPAT(SetHashSalt) != NULL) {
++ EXPAT(SetHashSalt)(self->parser,
++ (unsigned long)_Py_HashSecret.prefix);
++ }
+
+ ALLOC(sizeof(XMLParserObject), "create expatparser");
+
+diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c
+index 2b4d31293c64..1f8c0d70a559 100644
+--- a/Modules/pyexpat.c
++++ b/Modules/pyexpat.c
+@@ -2042,6 +2042,11 @@ MODULE_INITFUNC(void)
+ capi.SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler;
+ capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler;
+ capi.SetUserData = XML_SetUserData;
++#if XML_COMBINED_VERSION >= 20100
++ capi.SetHashSalt = XML_SetHashSalt;
++#else
++ capi.SetHashSalt = NULL;
++#endif
+
+ /* export using capsule */
+ capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL);
@@ -334,7 +334,7 @@
# Build the interpreter
- $(BUILDPYTHON): Modules/python.o $(LDLIBRARY)
+ $(BUILDPYTHON): Modules/python.o $(LIBRARY) $(LDLIBRARY)
- $(LINKCC) $(LDFLAGS) $(LINKFORSHARED) -o $@ \
+ $(LINKCC) $(CFLAGS) $(LDFLAGS) $(LINKFORSHARED) -o $@ \
Modules/python.o \
# First, look at Setup.config; configure may have set this for you.
-#crypt cryptmodule.c # -lcrypt # crypt(3); needs -lcrypt on some systems
-+crypt cryptmodule.c -lcrypt # crypt(3); needs -lcrypt on some systems
++crypt cryptmodule.c # -lcrypt # crypt(3); needs -lcrypt on some systems
# Some more UNIX dependent modules -- off by default, since these
-#nis nismodule.c -lnsl # Sun yellow pages -- not everywhere
-#termios termios.c # Steen Lumholt's termios module
-#resource resource.c # Jeremy Hylton's rlimit interface
-+nis nismodule.c -lnsl # Sun yellow pages -- not everywhere
++#nis nismodule.c -lnsl -ltirpc -I/usr/include/tirpc -I/usr/include/nsl -L/usr/lib/nsl
+termios termios.c # Steen Lumholt's termios module
+resource resource.c # Jeremy Hylton's rlimit interface
# The _tkinter module.
-@@ -333,7 +333,7 @@ GLHACK=-Dclear=__GLclear
- # *** Or uncomment this for Solaris:
- # -I/usr/openwin/include \
- # *** Uncomment and edit for Tix extension only:
--# -DWITH_TIX -ltix8.1.8.2 \
-+ -DWITH_TIX -ltix \
- # *** Uncomment and edit for BLT extension only:
- # -DWITH_BLT -I/usr/local/blt/blt8.0-unoff/include -lBLT8.0 \
- # *** Uncomment and edit for PIL (TkImaging) extension only:
@@ -352,7 +352,7 @@ GLHACK=-Dclear=__GLclear
# *** Uncomment for AIX:
# -lld \
return libpython
else:
diff --git a/Lib/site.py b/Lib/site.py
-index e8433b4..e8e6b50 100644
+index c360802..868b7cb 100644
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -288,12 +288,16 @@ def getsitepackages():
sitepackages.append(prefix)
+ sitepackages.append(os.path.join(prefix, "lib64", "site-packages"))
sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
- if sys.platform == "darwin":
- # for framework builds *only* we add the standard Apple
+ return sitepackages
+
diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py
-index 78c4809..3b9e74d 100644
+index d9a9324..e411e5c 100644
--- a/Lib/test/test_site.py
+++ b/Lib/test/test_site.py
-@@ -246,17 +246,20 @@ class HelperFunctionsTests(unittest.TestCase):
- self.assertEqual(dirs[2], wanted)
+@@ -235,17 +235,20 @@ class HelperFunctionsTests(unittest.TestCase):
+ self.assertEqual(dirs[0], wanted)
elif os.sep == '/':
- # OS X non-framwework builds, Linux, FreeBSD, etc
+ # OS X, Linux, FreeBSD, etc
- self.assertEqual(len(dirs), 2)
- wanted = os.path.join('xoxo', 'lib', 'python' + sys.version[:3],
+ self.assertEqual(len(dirs), 3)
class PthFile(object):
diff --git a/Makefile.pre.in b/Makefile.pre.in
-index 5741a4c..0faa5c5 100644
+index adae76b..ecb27f3 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -111,7 +111,7 @@ LIBDIR= @libdir@
# Detailed destination directories
BINLIBDEST= $(LIBDIR)/python$(VERSION)
diff --git a/Modules/Setup.dist b/Modules/Setup.dist
-index c70a0d6..051fd41 100644
+index fbfa1c1..138fb33 100644
--- a/Modules/Setup.dist
+++ b/Modules/Setup.dist
+@@ -231,7 +231,7 @@
+ # Some more UNIX dependent modules -- off by default, since these
+ # are not supported by all UNIX systems:
+
+-#nis nismodule.c -lnsl -ltirpc -I/usr/include/tirpc -I/usr/include/nsl -L/usr/lib/nsl
++#nis nismodule.c -lnsl -ltirpc -I/usr/include/tirpc -I/usr/include/nsl -L/usr/lib64/nsl
+ termios termios.c # Steen Lumholt's termios module
+ resource resource.c # Jeremy Hylton's rlimit interface
+
@@ -416,7 +416,7 @@ gdbm gdbmmodule.c -lgdbm
# Edit the variables DB and DBLIBVERto point to the db top directory
# and the subdirectory of PORT where you built it.
# Interface to the Expat XML parser
#
diff --git a/Modules/getpath.c b/Modules/getpath.c
-index 428684c..9ef6711 100644
+index fd33a01..c5c86fd 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -108,7 +108,7 @@ static char prefix[MAXPATHLEN+1];
static void
reduce(char *dir)
-@@ -550,7 +550,7 @@ calculate_path(void)
+@@ -548,7 +548,7 @@ calculate_path(void)
fprintf(stderr,
"Could not find platform dependent libraries <exec_prefix>\n");
strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN);
/* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
diff --git a/setup.py b/setup.py
-index 55c4f5d..19efe82 100644
+index 99ac359..859b6c4 100644
--- a/setup.py
+++ b/setup.py
@@ -456,7 +456,7 @@ class PyBuildExt(build_ext):
name = python
major_ver = 2.7
-version = %{major_ver}.12
-release = 2
+version = %{major_ver}.15
+release = 1
thisapp = Python-%{version}
groups = Development/Languages
export CFLAGS += -D_GNU_SOURCE -fwrapv
export CPPFLAGS = %(pkg-config --cflags-only-I libffi)
export OPT = %{CFLAGS}
+ export CC = gcc
+ export LINKCC = gcc
if "%{lib}" == "lib64"
- patches += %{DIR_SOURCE}/python-2.7.12-lib64.patch
+ patches += %{DIR_SOURCE}/python-2.7.13-lib64.patch
patches += %{DIR_SOURCE}/python-2.7-lib64-sysconfig.patch
end