summaryrefslogtreecommitdiff
path: root/debian/patches
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2017-09-29 20:35:09 +0300
committerIgor Pashev <pashev.igor@gmail.com>2017-09-29 20:35:09 +0300
commit377002e7300431b68f3548d9fd2c7f99cf883939 (patch)
treed167dd4a5d88ebbc3e2d5cea061848d7ee8f6e89 /debian/patches
downloadpython3.8-377002e7300431b68f3548d9fd2c7f99cf883939.tar.gz
Imported python3.6 3.6.3~rc1debian/3.6.3_rc1
Diffstat (limited to 'debian/patches')
-rw-r--r--debian/patches/bdist-wininst-notfound.diff19
-rw-r--r--debian/patches/ctypes-arm.diff34
-rw-r--r--debian/patches/deb-locations.diff30
-rw-r--r--debian/patches/deb-setup.diff33
-rw-r--r--debian/patches/disable-sem-check.diff38
-rw-r--r--debian/patches/disable-some-tests.diff14
-rw-r--r--debian/patches/distutils-install-layout.diff278
-rw-r--r--debian/patches/distutils-link.diff24
-rw-r--r--debian/patches/distutils-sysconfig.diff45
-rw-r--r--debian/patches/ensurepip-disabled.diff87
-rw-r--r--debian/patches/ensurepip-wheels.diff121
-rw-r--r--debian/patches/ext-no-libpython-link.diff24
-rw-r--r--debian/patches/gdbm-import.diff12
-rw-r--r--debian/patches/git-updates.diff4
-rw-r--r--debian/patches/langpack-gettext.diff36
-rw-r--r--debian/patches/lib-argparse.diff22
-rw-r--r--debian/patches/lib2to3-no-pickled-grammar.diff92
-rw-r--r--debian/patches/link-opt.diff26
-rw-r--r--debian/patches/link-timemodule.diff13
-rw-r--r--debian/patches/locale-module.diff19
-rw-r--r--debian/patches/lto-link-flags.diff22
-rw-r--r--debian/patches/mangle-fstack-protector.diff26
-rw-r--r--debian/patches/multiarch-extname.diff92
-rw-r--r--debian/patches/multiarch.diff52
-rw-r--r--debian/patches/platform-lsbrelease.diff65
-rw-r--r--debian/patches/profiled-build.diff23
-rw-r--r--debian/patches/pydoc-use-pager.diff15
-rw-r--r--debian/patches/pyhash.diff67
-rw-r--r--debian/patches/reproducible-buildinfo.diff15
-rw-r--r--debian/patches/series34
-rw-r--r--debian/patches/setup-modules.diff52
-rw-r--r--debian/patches/sysconfig-debian-schemes.diff67
-rw-r--r--debian/patches/tempfile-minimal.diff169
-rw-r--r--debian/patches/test-no-random-order.diff14
-rw-r--r--debian/patches/tkinter-import.diff18
-rw-r--r--debian/patches/update-tls-protocol.diff79
-rw-r--r--debian/patches/update-tls-protocol2.diff98
37 files changed, 1879 insertions, 0 deletions
diff --git a/debian/patches/bdist-wininst-notfound.diff b/debian/patches/bdist-wininst-notfound.diff
new file mode 100644
index 0000000..27e9024
--- /dev/null
+++ b/debian/patches/bdist-wininst-notfound.diff
@@ -0,0 +1,19 @@
+# DP: suggest installation of the pythonX.Y-dev package, if bdist_wininst
+# DP: cannot find the wininst-* files.
+
+Index: b/Lib/distutils/command/bdist_wininst.py
+===================================================================
+--- a/Lib/distutils/command/bdist_wininst.py
++++ b/Lib/distutils/command/bdist_wininst.py
+@@ -358,7 +358,10 @@ class bdist_wininst(Command):
+ sfix = ''
+
+ filename = os.path.join(directory, "wininst-%s%s.exe" % (bv, sfix))
+- f = open(filename, "rb")
++ try:
++ f = open(filename, "rb")
++ except IOError as e:
++ raise DistutilsFileError(str(e) + ', %s not included in the Debian packages.' % filename)
+ try:
+ return f.read()
+ finally:
diff --git a/debian/patches/ctypes-arm.diff b/debian/patches/ctypes-arm.diff
new file mode 100644
index 0000000..5be98b6
--- /dev/null
+++ b/debian/patches/ctypes-arm.diff
@@ -0,0 +1,34 @@
+Index: b/Lib/ctypes/util.py
+===================================================================
+--- a/Lib/ctypes/util.py
++++ b/Lib/ctypes/util.py
+@@ -247,16 +247,27 @@ elif os.name == "posix":
+
+ def _findSoname_ldconfig(name):
+ import struct
++ # XXX this code assumes that we know all unames and that a single
++ # ABI is supported per uname; instead we should find what the
++ # ABI is (e.g. check ABI of current process) or simply ask libc
++ # to load the library for us
++ uname = os.uname()
++ # ARM has a variety of unames, e.g. armv7l
++ if uname.machine.startswith("arm"):
++ machine = "arm"
+ if struct.calcsize('l') == 4:
+- machine = os.uname().machine + '-32'
++ machine = uname.machine + '-32'
+ else:
+- machine = os.uname().machine + '-64'
++ machine = uname.machine + '-64'
+ mach_map = {
+ 'x86_64-64': 'libc6,x86-64',
+ 'ppc64-64': 'libc6,64bit',
+ 'sparc64-64': 'libc6,64bit',
+ 's390x-64': 'libc6,64bit',
+ 'ia64-64': 'libc6,IA-64',
++ # this actually breaks on biarch or multiarch as the first
++ # library wins; uname doesn't tell us which ABI we're using
++ 'arm-32': 'libc6(,hard-float)?',
+ }
+ abi_type = mach_map.get(machine, 'libc6')
+
diff --git a/debian/patches/deb-locations.diff b/debian/patches/deb-locations.diff
new file mode 100644
index 0000000..b3b2ad9
--- /dev/null
+++ b/debian/patches/deb-locations.diff
@@ -0,0 +1,30 @@
+# DP: adjust locations of directories to debian policy
+
+Index: b/Lib/pydoc.py
+===================================================================
+--- a/Lib/pydoc.py
++++ b/Lib/pydoc.py
+@@ -28,6 +28,10 @@ to a file named "<name>.html".
+
+ Module docs for core modules are assumed to be in
+
++ /usr/share/doc/pythonX.Y/html/library
++
++if the pythonX.Y-doc package is installed or in
++
+ https://docs.python.org/X.Y/library/
+
+ This can be overridden by setting the PYTHONDOCS environment variable
+Index: b/Misc/python.man
+===================================================================
+--- a/Misc/python.man
++++ b/Misc/python.man
+@@ -327,7 +327,7 @@ exception). Error messages are written
+ These are subject to difference depending on local installation
+ conventions; ${prefix} and ${exec_prefix} are installation-dependent
+ and should be interpreted as for GNU software; they may be the same.
+-The default for both is \fI/usr/local\fP.
++On Debian GNU/{Hurd,Linux} the default for both is \fI/usr\fP.
+ .IP \fI${exec_prefix}/bin/python\fP
+ Recommended location of the interpreter.
+ .PP
diff --git a/debian/patches/deb-setup.diff b/debian/patches/deb-setup.diff
new file mode 100644
index 0000000..08ce316
--- /dev/null
+++ b/debian/patches/deb-setup.diff
@@ -0,0 +1,33 @@
+# DP: Don't include /usr/local/include and /usr/local/lib as gcc search paths
+
+Index: b/setup.py
+===================================================================
+--- a/setup.py
++++ b/setup.py
+@@ -262,8 +262,10 @@ class PyBuildExt(build_ext):
+ # unfortunately, distutils doesn't let us provide separate C and C++
+ # compilers
+ if compiler is not None:
+- (ccshared,cflags) = sysconfig.get_config_vars('CCSHARED','CFLAGS')
+- args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags
++ (ccshared, cppflags, cflags) = \
++ sysconfig.get_config_vars('CCSHARED', 'CPPFLAGS', 'CFLAGS')
++ cppflags = ' '.join([f for f in cppflags.split() if not f.startswith('-I')])
++ args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cppflags + ' ' + cflags
+ self.compiler.set_executables(**args)
+
+ build_ext.build_extensions(self)
+@@ -487,12 +489,7 @@ class PyBuildExt(build_ext):
+ return ['m']
+
+ def detect_modules(self):
+- # Ensure that /usr/local is always used, but the local build
+- # directories (i.e. '.' and 'Include') must be first. See issue
+- # 10520.
+- if not cross_compiling:
+- add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
+- add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
++ # On Debian /usr/local is always used, so we don't include it twice
+ # only change this for cross builds for 3.3, issues on Mageia
+ if cross_compiling:
+ self.add_gcc_paths()
diff --git a/debian/patches/disable-sem-check.diff b/debian/patches/disable-sem-check.diff
new file mode 100644
index 0000000..cb1630f
--- /dev/null
+++ b/debian/patches/disable-sem-check.diff
@@ -0,0 +1,38 @@
+# DP: Assume working semaphores, don't rely on running kernel for the check.
+
+Index: b/configure.ac
+===================================================================
+--- a/configure.ac
++++ b/configure.ac
+@@ -4496,8 +4496,13 @@ int main(void) {
+ AC_MSG_RESULT($ac_cv_posix_semaphores_enabled)
+ if test $ac_cv_posix_semaphores_enabled = no
+ then
+- AC_DEFINE(POSIX_SEMAPHORES_NOT_ENABLED, 1,
+- [Define if POSIX semaphores aren't enabled on your system])
++ case $ac_sys_system in
++ Linux*) # assume yes, see https://launchpad.net/bugs/630511
++ ;;
++ *)
++ AC_DEFINE(POSIX_SEMAPHORES_NOT_ENABLED, 1,
++ [Define if POSIX semaphores aren't enabled on your system])
++ esac
+ fi
+
+ # Multiprocessing check for broken sem_getvalue
+@@ -4532,8 +4537,13 @@ int main(void){
+ AC_MSG_RESULT($ac_cv_broken_sem_getvalue)
+ if test $ac_cv_broken_sem_getvalue = yes
+ then
+- AC_DEFINE(HAVE_BROKEN_SEM_GETVALUE, 1,
+- [define to 1 if your sem_getvalue is broken.])
++ case $ac_sys_system in
++ Linux*) # assume yes, see https://launchpad.net/bugs/630511
++ ;;
++ *)
++ AC_DEFINE(HAVE_BROKEN_SEM_GETVALUE, 1,
++ [define to 1 if your sem_getvalue is broken.])
++ esac
+ fi
+
+ AC_CHECK_DECLS([RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL, RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND], [], [], [[#include <dlfcn.h>]])
diff --git a/debian/patches/disable-some-tests.diff b/debian/patches/disable-some-tests.diff
new file mode 100644
index 0000000..ddec2cd
--- /dev/null
+++ b/debian/patches/disable-some-tests.diff
@@ -0,0 +1,14 @@
+# DP: Disable some failing tests we are not interested in
+
+Index: b/Lib/distutils/tests/test_build_ext.py
+===================================================================
+--- a/Lib/distutils/tests/test_build_ext.py
++++ b/Lib/distutils/tests/test_build_ext.py
+@@ -102,6 +102,7 @@ class BuildExtTestCase(TempdirManager,
+ build_ext.USER_BASE = self.old_user_base
+ super(BuildExtTestCase, self).tearDown()
+
++ @unittest.skip('Skipping failing Solaris test')
+ def test_solaris_enable_shared(self):
+ dist = Distribution({'name': 'xx'})
+ cmd = self.build_ext(dist)
diff --git a/debian/patches/distutils-install-layout.diff b/debian/patches/distutils-install-layout.diff
new file mode 100644
index 0000000..9ca8b00
--- /dev/null
+++ b/debian/patches/distutils-install-layout.diff
@@ -0,0 +1,278 @@
+# DP: distutils: Add an option --install-layout=deb, which
+# DP: - installs into $prefix/dist-packages instead of $prefix/site-packages.
+# DP: - doesn't encode the python version into the egg name.
+
+Index: b/Lib/distutils/command/install_egg_info.py
+===================================================================
+--- a/Lib/distutils/command/install_egg_info.py
++++ b/Lib/distutils/command/install_egg_info.py
+@@ -14,18 +14,38 @@ class install_egg_info(Command):
+ description = "Install package's PKG-INFO metadata as an .egg-info file"
+ user_options = [
+ ('install-dir=', 'd', "directory to install to"),
++ ('install-layout', None, "custom installation layout"),
+ ]
+
+ def initialize_options(self):
+ self.install_dir = None
++ self.install_layout = None
++ self.prefix_option = None
+
+ def finalize_options(self):
+ self.set_undefined_options('install_lib',('install_dir','install_dir'))
+- basename = "%s-%s-py%d.%d.egg-info" % (
+- to_filename(safe_name(self.distribution.get_name())),
+- to_filename(safe_version(self.distribution.get_version())),
+- *sys.version_info[:2]
+- )
++ self.set_undefined_options('install',('install_layout','install_layout'))
++ self.set_undefined_options('install',('prefix_option','prefix_option'))
++ if self.install_layout:
++ if not self.install_layout.lower() in ['deb', 'unix']:
++ raise DistutilsOptionError(
++ "unknown value for --install-layout")
++ no_pyver = (self.install_layout.lower() == 'deb')
++ elif self.prefix_option:
++ no_pyver = False
++ else:
++ no_pyver = True
++ if no_pyver:
++ basename = "%s-%s.egg-info" % (
++ to_filename(safe_name(self.distribution.get_name())),
++ to_filename(safe_version(self.distribution.get_version()))
++ )
++ else:
++ basename = "%s-%s-py%d.%d.egg-info" % (
++ to_filename(safe_name(self.distribution.get_name())),
++ to_filename(safe_version(self.distribution.get_version())),
++ *sys.version_info[:2]
++ )
+ self.target = os.path.join(self.install_dir, basename)
+ self.outputs = [self.target]
+
+Index: b/Lib/distutils/command/install.py
+===================================================================
+--- a/Lib/distutils/command/install.py
++++ b/Lib/distutils/command/install.py
+@@ -35,6 +35,20 @@ INSTALL_SCHEMES = {
+ 'scripts': '$base/bin',
+ 'data' : '$base',
+ },
++ 'unix_local': {
++ 'purelib': '$base/local/lib/python$py_version_short/dist-packages',
++ 'platlib': '$platbase/local/lib/python$py_version_short/dist-packages',
++ 'headers': '$base/local/include/python$py_version_short/$dist_name',
++ 'scripts': '$base/local/bin',
++ 'data' : '$base/local',
++ },
++ 'deb_system': {
++ 'purelib': '$base/lib/python3/dist-packages',
++ 'platlib': '$platbase/lib/python3/dist-packages',
++ 'headers': '$base/include/python$py_version_short/$dist_name',
++ 'scripts': '$base/bin',
++ 'data' : '$base',
++ },
+ 'unix_home': {
+ 'purelib': '$base/lib/python',
+ 'platlib': '$base/lib/python',
+@@ -131,6 +145,9 @@ class install(Command):
+
+ ('record=', None,
+ "filename in which to record list of installed files"),
++
++ ('install-layout=', None,
++ "installation layout to choose (known values: deb, unix)"),
+ ]
+
+ boolean_options = ['compile', 'force', 'skip-build']
+@@ -151,6 +168,7 @@ class install(Command):
+ self.exec_prefix = None
+ self.home = None
+ self.user = 0
++ self.prefix_option = None
+
+ # These select only the installation base; it's up to the user to
+ # specify the installation scheme (currently, that means supplying
+@@ -172,6 +190,9 @@ class install(Command):
+ self.install_userbase = USER_BASE
+ self.install_usersite = USER_SITE
+
++ # enable custom installation, known values: deb
++ self.install_layout = None
++
+ self.compile = None
+ self.optimize = None
+
+@@ -413,6 +434,7 @@ class install(Command):
+ self.install_base = self.install_platbase = self.home
+ self.select_scheme("unix_home")
+ else:
++ self.prefix_option = self.prefix
+ if self.prefix is None:
+ if self.exec_prefix is not None:
+ raise DistutilsOptionError(
+@@ -427,7 +449,26 @@ class install(Command):
+
+ self.install_base = self.prefix
+ self.install_platbase = self.exec_prefix
+- self.select_scheme("unix_prefix")
++ if self.install_layout:
++ if self.install_layout.lower() in ['deb']:
++ self.select_scheme("deb_system")
++ elif self.install_layout.lower() in ['unix']:
++ self.select_scheme("unix_prefix")
++ else:
++ raise DistutilsOptionError(
++ "unknown value for --install-layout")
++ elif ((self.prefix_option and
++ os.path.normpath(self.prefix) != '/usr/local')
++ or sys.base_prefix != sys.prefix
++ or 'PYTHONUSERBASE' in os.environ
++ or 'VIRTUAL_ENV' in os.environ
++ or 'real_prefix' in sys.__dict__):
++ self.select_scheme("unix_prefix")
++ else:
++ if os.path.normpath(self.prefix) == '/usr/local':
++ self.prefix = self.exec_prefix = '/usr'
++ self.install_base = self.install_platbase = '/usr'
++ self.select_scheme("unix_local")
+
+ def finalize_other(self):
+ """Finalizes options for non-posix platforms"""
+Index: b/Lib/distutils/sysconfig.py
+===================================================================
+--- a/Lib/distutils/sysconfig.py
++++ b/Lib/distutils/sysconfig.py
+@@ -122,6 +122,7 @@ def get_python_lib(plat_specific=0, stan
+ If 'prefix' is supplied, use it instead of sys.base_prefix or
+ sys.base_exec_prefix -- i.e., ignore 'plat_specific'.
+ """
++ is_default_prefix = not prefix or os.path.normpath(prefix) in ('/usr', '/usr/local')
+ if prefix is None:
+ if standard_lib:
+ prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX
+@@ -133,6 +134,12 @@ def get_python_lib(plat_specific=0, stan
+ "lib", "python" + get_python_version())
+ if standard_lib:
+ return libpython
++ elif (is_default_prefix and
++ 'PYTHONUSERBASE' not in os.environ and
++ 'VIRTUAL_ENV' not in os.environ and
++ 'real_prefix' not in sys.__dict__ and
++ sys.prefix == sys.base_prefix):
++ return os.path.join(prefix, "lib", "python3", "dist-packages")
+ else:
+ return os.path.join(libpython, "site-packages")
+ elif os.name == "nt":
+Index: b/Lib/site.py
+===================================================================
+--- a/Lib/site.py
++++ b/Lib/site.py
+@@ -7,12 +7,18 @@
+ This will append site-specific paths to the module search path. On
+ Unix (including Mac OSX), it starts with sys.prefix and
+ sys.exec_prefix (if different) and appends
+-lib/python<version>/site-packages.
++lib/python3/dist-packages.
+ On other platforms (such as Windows), it tries each of the
+ prefixes directly, as well as with lib/site-packages appended. The
+ resulting directories, if they exist, are appended to sys.path, and
+ also inspected for path configuration files.
+
++For Debian and derivatives, this sys.path is augmented with directories
++for packages distributed within the distribution. Local addons go
++into /usr/local/lib/python<version>/dist-packages, Debian addons
++install into /usr/lib/python3/dist-packages.
++/usr/lib/python<version>/site-packages is not used.
++
+ If a file named "pyvenv.cfg" exists one directory above sys.executable,
+ sys.prefix and sys.exec_prefix are set to that directory and
+ it is also checked for site-packages (sys.base_prefix and
+@@ -304,9 +310,20 @@ def getsitepackages(prefixes=None):
+ seen.add(prefix)
+
+ if os.sep == '/':
++ if 'VIRTUAL_ENV' in os.environ or sys.base_prefix != sys.prefix:
++ sitepackages.append(os.path.join(prefix, "lib",
++ "python" + sys.version[:3],
++ "site-packages"))
++ sitepackages.append(os.path.join(prefix, "local/lib",
++ "python" + sys.version[:3],
++ "dist-packages"))
++ sitepackages.append(os.path.join(prefix, "lib",
++ "python3",
++ "dist-packages"))
++ # this one is deprecated for Debian
+ sitepackages.append(os.path.join(prefix, "lib",
+- "python%d.%d" % sys.version_info[:2],
+- "site-packages"))
++ "python" + sys.version[:3],
++ "dist-packages"))
+ else:
+ sitepackages.append(prefix)
+ sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
+Index: b/Lib/test/test_site.py
+===================================================================
+--- a/Lib/test/test_site.py
++++ b/Lib/test/test_site.py
+@@ -260,10 +260,10 @@ class HelperFunctionsTests(unittest.Test
+ self.assertEqual(dirs[1], wanted)
+ elif os.sep == '/':
+ # OS X non-framwework builds, Linux, FreeBSD, etc
+- self.assertEqual(len(dirs), 1)
+- wanted = os.path.join('xoxo', 'lib',
++ self.assertEqual(len(dirs), 3)
++ wanted = os.path.join('xoxo', 'local', 'lib',
+ 'python%d.%d' % sys.version_info[:2],
+- 'site-packages')
++ 'dist-packages')
+ self.assertEqual(dirs[0], wanted)
+ else:
+ # other platforms
+Index: b/Lib/distutils/tests/test_bdist_dumb.py
+===================================================================
+--- a/Lib/distutils/tests/test_bdist_dumb.py
++++ b/Lib/distutils/tests/test_bdist_dumb.py
+@@ -85,7 +85,7 @@ class BuildDumbTestCase(support.TempdirM
+ fp.close()
+
+ contents = sorted(os.path.basename(fn) for fn in contents)
+- wanted = ['foo-0.1-py%s.%s.egg-info' % sys.version_info[:2], 'foo.py']
++ wanted = ['foo-0.1.egg-info', 'foo.py']
+ if not sys.dont_write_bytecode:
+ wanted.append('foo.%s.pyc' % sys.implementation.cache_tag)
+ self.assertEqual(contents, sorted(wanted))
+Index: b/Lib/distutils/tests/test_install.py
+===================================================================
+--- a/Lib/distutils/tests/test_install.py
++++ b/Lib/distutils/tests/test_install.py
+@@ -193,7 +193,7 @@ class InstallTestCase(support.TempdirMan
+ found = [os.path.basename(line) for line in content.splitlines()]
+ expected = ['hello.py', 'hello.%s.pyc' % sys.implementation.cache_tag,
+ 'sayhi',
+- 'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
++ 'UNKNOWN-0.0.0.egg-info']
+ self.assertEqual(found, expected)
+
+ def test_record_extensions(self):
+@@ -226,7 +226,7 @@ class InstallTestCase(support.TempdirMan
+
+ found = [os.path.basename(line) for line in content.splitlines()]
+ expected = [_make_ext_name('xx'),
+- 'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
++ 'UNKNOWN-0.0.0.egg-info']
+ self.assertEqual(found, expected)
+
+ def test_debug_mode(self):
+Index: b/Lib/pydoc.py
+===================================================================
+--- a/Lib/pydoc.py
++++ b/Lib/pydoc.py
+@@ -417,6 +417,7 @@ class Doc:
+ 'marshal', 'posix', 'signal', 'sys',
+ '_thread', 'zipimport') or
+ (file.startswith(basedir) and
++ not file.startswith(os.path.join(basedir, 'dist-packages')) and
+ not file.startswith(os.path.join(basedir, 'site-packages')))) and
+ object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
+ if docloc.startswith(("http://", "https://")):
diff --git a/debian/patches/distutils-link.diff b/debian/patches/distutils-link.diff
new file mode 100644
index 0000000..b8ad3cf
--- /dev/null
+++ b/debian/patches/distutils-link.diff
@@ -0,0 +1,24 @@
+# DP: Don't add standard library dirs to library_dirs and runtime_library_dirs.
+
+Index: b/Lib/distutils/unixccompiler.py
+===================================================================
+--- a/Lib/distutils/unixccompiler.py
++++ b/Lib/distutils/unixccompiler.py
+@@ -155,6 +155,17 @@ class UnixCCompiler(CCompiler):
+ runtime_library_dirs)
+ libraries, library_dirs, runtime_library_dirs = fixed_args
+
++ # filter out standard library paths, which are not explicitely needed
++ # for linking
++ system_libdirs = ['/lib', '/lib64', '/usr/lib', '/usr/lib64']
++ multiarch = sysconfig.get_config_var("MULTIARCH")
++ if multiarch:
++ system_libdirs.extend(['/lib/%s' % multiarch, '/usr/lib/%s' % multiarch])
++ library_dirs = [dir for dir in library_dirs
++ if not dir in system_libdirs]
++ runtime_library_dirs = [dir for dir in runtime_library_dirs
++ if not dir in system_libdirs]
++
+ lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs,
+ libraries)
+ if not isinstance(output_dir, (str, type(None))):
diff --git a/debian/patches/distutils-sysconfig.diff b/debian/patches/distutils-sysconfig.diff
new file mode 100644
index 0000000..c12e6b3
--- /dev/null
+++ b/debian/patches/distutils-sysconfig.diff
@@ -0,0 +1,45 @@
+# DP: Get CONFIGURE_CFLAGS, CONFIGURE_CPPFLAGS, CONFIGURE_LDFLAGS from
+# DP: the python build, when CFLAGS, CPPFLAGS, LDSHARED) are not set
+# DP: in the environment.
+
+Index: b/Lib/distutils/sysconfig.py
+===================================================================
+--- a/Lib/distutils/sysconfig.py
++++ b/Lib/distutils/sysconfig.py
+@@ -177,9 +177,11 @@ def customize_compiler(compiler):
+ _osx_support.customize_compiler(_config_vars)
+ _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True'
+
+- (cc, cxx, opt, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \
++ (cc, cxx, opt, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags,
++ configure_cppflags, configure_cflags, configure_ldflags) = \
+ get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
+- 'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS')
++ 'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS',
++ 'CONFIGURE_CPPFLAGS', 'CONFIGURE_CFLAGS', 'CONFIGURE_LDFLAGS')
+
+ if 'CC' in os.environ:
+ newcc = os.environ['CC']
+@@ -200,13 +202,22 @@ def customize_compiler(compiler):
+ cpp = cc + " -E" # not always
+ if 'LDFLAGS' in os.environ:
+ ldshared = ldshared + ' ' + os.environ['LDFLAGS']
++ elif configure_ldflags:
++ ldshared = ldshared + ' ' + configure_ldflags
+ if 'CFLAGS' in os.environ:
+ cflags = opt + ' ' + os.environ['CFLAGS']
+ ldshared = ldshared + ' ' + os.environ['CFLAGS']
++ elif configure_cflags:
++ cflags = opt + ' ' + configure_cflags
++ ldshared = ldshared + ' ' + configure_cflags
+ if 'CPPFLAGS' in os.environ:
+ cpp = cpp + ' ' + os.environ['CPPFLAGS']
+ cflags = cflags + ' ' + os.environ['CPPFLAGS']
+ ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
++ elif configure_cppflags:
++ cpp = cpp + ' ' + configure_cppflags
++ cflags = cflags + ' ' + configure_cppflags
++ ldshared = ldshared + ' ' + configure_cppflags
+ if 'AR' in os.environ:
+ ar = os.environ['AR']
+ if 'ARFLAGS' in os.environ:
diff --git a/debian/patches/ensurepip-disabled.diff b/debian/patches/ensurepip-disabled.diff
new file mode 100644
index 0000000..f19b36a
--- /dev/null
+++ b/debian/patches/ensurepip-disabled.diff
@@ -0,0 +1,87 @@
+# DP: Disable ensurepip for the system installation, only enable it for virtual environments.
+
+Index: b/Lib/ensurepip/__init__.py
+===================================================================
+--- a/Lib/ensurepip/__init__.py
++++ b/Lib/ensurepip/__init__.py
+@@ -8,6 +8,34 @@ import tempfile
+
+ __all__ = ["version", "bootstrap"]
+
++def _ensurepip_is_disabled_in_debian_for_system():
++ # Detect if ensurepip is being executed inside of a python-virtualenv
++ # environment and return early if so.
++ if hasattr(sys, 'real_prefix'):
++ return
++
++ # Detect if ensurepip is being executed inside of a stdlib venv
++ # environment and return early if so.
++ if sys.prefix != getattr(sys, "base_prefix", sys.prefix):
++ return
++
++ # If we've gotten here, then we are running inside of the system Python
++ # and we don't want to use ensurepip to install into the system Python
++ # so instead we'll redirect the user to using dpkg and apt-get.
++ print('''\
++ensurepip is disabled in Debian/Ubuntu for the system python.
++
++Python modules for the system python are usually handled by dpkg and apt-get.
++
++ apt-get install python-<module name>
++
++Install the python-pip package to use pip itself. Using pip together
++with the system python might have unexpected results for any system installed
++module, so use it on your own risk, or make sure to only use it in virtual
++environments.
++''')
++ sys.exit(1)
++
+
+ _PROJECTS = [
+ "setuptools",
+@@ -56,6 +84,11 @@ def bootstrap(*, root=None, upgrade=Fals
+
+ Note that calling this function will alter both sys.path and os.environ.
+ """
++
++ # Ensure that we are only running this inside of a virtual environment
++ # of some kind.
++ _ensurepip_is_disabled_in_debian_for_system()
++
+ if altinstall and default_pip:
+ raise ValueError("Cannot use altinstall and default_pip together")
+
+Index: b/Lib/venv/__init__.py
+===================================================================
+--- a/Lib/venv/__init__.py
++++ b/Lib/venv/__init__.py
+@@ -242,7 +242,28 @@ class EnvBuilder:
+ # intended for the global Python environment
+ cmd = [context.env_exe, '-Im', 'ensurepip', '--upgrade',
+ '--default-pip']
+- subprocess.check_output(cmd, stderr=subprocess.STDOUT)
++ # Debian 2015-09-18 barry@debian.org: <python>-venv is a separate
++ # binary package which might not be installed. In that case, the
++ # following command will produce an unhelpful error. Let's make it
++ # more user friendly.
++ try:
++ subprocess.check_output(
++ cmd, stderr=subprocess.STDOUT,
++ universal_newlines=True)
++ except subprocess.CalledProcessError:
++ print("""\
++The virtual environment was not created successfully because ensurepip is not
++available. On Debian/Ubuntu systems, you need to install the python3-venv
++package using the following command.
++
++ apt-get install python3-venv
++
++You may need to use sudo with that command. After installing the python3-venv
++package, recreate your virtual environment.
++
++Failing command: {}
++""".format(cmd))
++ sys.exit(1)
+
+ def setup_scripts(self, context):
+ """
diff --git a/debian/patches/ensurepip-wheels.diff b/debian/patches/ensurepip-wheels.diff
new file mode 100644
index 0000000..df5de92
--- /dev/null
+++ b/debian/patches/ensurepip-wheels.diff
@@ -0,0 +1,121 @@
+Index: b/Lib/ensurepip/__init__.py
+===================================================================
+--- a/Lib/ensurepip/__init__.py
++++ b/Lib/ensurepip/__init__.py
+@@ -1,3 +1,4 @@
++import glob
+ import os
+ import os.path
+ import pkgutil
+@@ -8,13 +9,10 @@ import tempfile
+ __all__ = ["version", "bootstrap"]
+
+
+-_SETUPTOOLS_VERSION = "28.8.0"
+-
+-_PIP_VERSION = "9.0.1"
+-
+ _PROJECTS = [
+- ("setuptools", _SETUPTOOLS_VERSION),
+- ("pip", _PIP_VERSION),
++ "setuptools",
++ "pip",
++ "pkg_resources",
+ ]
+
+
+@@ -32,7 +30,10 @@ def version():
+ """
+ Returns a string specifying the bundled version of pip.
+ """
+- return _PIP_VERSION
++ wheel_names = glob.glob('/usr/share/python-wheels/pip-*.whl')
++ assert len(wheel_names) == 1, wheel_names
++ return os.path.basename(wheel_names[0]).split('-')[1]
++
+
+ def _disable_pip_configuration_settings():
+ # We deliberately ignore all pip environment variables
+@@ -73,20 +74,44 @@ def bootstrap(*, root=None, upgrade=Fals
+ # omit pip and easy_install
+ os.environ["ENSUREPIP_OPTIONS"] = "install"
+
++ # Debian: The bundled wheels are useless to us because we must use ones
++ # crafted from source code in the archive. As we build the virtual
++ # environment, copy the wheels from the system location into the virtual
++ # environment, and place those wheels on sys.path.
++ def copy_wheels(wheels, destdir, paths):
++ for project in wheels:
++ wheel_names = glob.glob(
++ '/usr/share/python-wheels/{}-*.whl'.format(project))
++ if len(wheel_names) == 0:
++ raise RuntimeError('missing dependency wheel %s' % project)
++ assert len(wheel_names) == 1, wheel_names
++ wheel_name = os.path.basename(wheel_names[0])
++ path = os.path.join('/usr/share/python-wheels', wheel_name)
++ with open(path, 'rb') as fp:
++ whl = fp.read()
++ dest = os.path.join(destdir, wheel_name)
++ with open(dest, 'wb') as fp:
++ fp.write(whl)
++ paths.append(dest)
++
+ with tempfile.TemporaryDirectory() as tmpdir:
++ # This directory is a "well known directory" which Debian has patched
++ # pip to look in when attempting to locate wheels to use to satisfy
++ # the dependencies that pip normally bundles but Debian has debundled.
++ # This is critically important and if this directory changes then both
++ # python-pip and python-virtualenv needs updated to match.
++ venv_wheel_dir = os.path.join(sys.prefix, 'share', 'python-wheels')
++ os.makedirs(venv_wheel_dir, exist_ok=True)
++ dependencies = [
++ os.path.basename(whl).split('-')[0]
++ for whl in glob.glob('/usr/share/python-wheels/*.whl')
++ ]
++ copy_wheels(dependencies, venv_wheel_dir, sys.path)
++
+ # Put our bundled wheels into a temporary directory and construct the
+ # additional paths that need added to sys.path
+ 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)
+-
+- additional_paths.append(os.path.join(tmpdir, wheel_name))
++ copy_wheels(_PROJECTS, tmpdir, additional_paths)
+
+ # Construct the arguments to be passed to the pip command
+ args = ["install", "--no-index", "--find-links", tmpdir]
+@@ -99,7 +124,7 @@ def bootstrap(*, root=None, upgrade=Fals
+ if verbosity:
+ args += ["-" + "v" * verbosity]
+
+- _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
++ _run_pip(args + _PROJECTS, additional_paths)
+
+ def _uninstall_helper(*, verbosity=0):
+ """Helper to support a clean default uninstall process on Windows
+@@ -113,7 +138,8 @@ def _uninstall_helper(*, verbosity=0):
+ return
+
+ # If the pip version doesn't match the bundled one, leave it alone
+- if pip.__version__ != _PIP_VERSION:
++ # Disabled for Debian, always using the version from the python3-pip package.
++ if False and pip.__version__ != _PIP_VERSION:
+ msg = ("ensurepip will only uninstall a matching version "
+ "({!r} installed, {!r} bundled)")
+ print(msg.format(pip.__version__, _PIP_VERSION), file=sys.stderr)
+@@ -126,7 +152,7 @@ def _uninstall_helper(*, verbosity=0):
+ if verbosity:
+ args += ["-" + "v" * verbosity]
+
+- _run_pip(args + [p[0] for p in reversed(_PROJECTS)])
++ _run_pip(args + reversed(_PROJECTS))
+
+
+ def _main(argv=None):
diff --git a/debian/patches/ext-no-libpython-link.diff b/debian/patches/ext-no-libpython-link.diff
new file mode 100644
index 0000000..627d9d1
--- /dev/null
+++ b/debian/patches/ext-no-libpython-link.diff
@@ -0,0 +1,24 @@
+# DP: Don't link extensions with the shared libpython library.
+
+Index: b/Lib/distutils/command/build_ext.py
+===================================================================
+--- a/Lib/distutils/command/build_ext.py
++++ b/Lib/distutils/command/build_ext.py
+@@ -230,7 +230,7 @@ class build_ext(Command):
+ # For building extensions with a shared Python library,
+ # Python's library directory must be appended to library_dirs
+ # See Issues: #1600860, #4366
+- if (sysconfig.get_config_var('Py_ENABLE_SHARED')):
++ if False and (sysconfig.get_config_var('Py_ENABLE_SHARED')):
+ if not sysconfig.python_build:
+ # building third party extensions
+ self.library_dirs.append(sysconfig.get_config_var('LIBDIR'))
+@@ -746,7 +746,7 @@ class build_ext(Command):
+ return ext.libraries
+ else:
+ from distutils import sysconfig
+- if sysconfig.get_config_var('Py_ENABLE_SHARED'):
++ if False and sysconfig.get_config_var('Py_ENABLE_SHARED'):
+ pythonlib = 'python{}.{}{}'.format(
+ sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff,
+ sysconfig.get_config_var('ABIFLAGS'))
diff --git a/debian/patches/gdbm-import.diff b/debian/patches/gdbm-import.diff
new file mode 100644
index 0000000..2be2934
--- /dev/null
+++ b/debian/patches/gdbm-import.diff
@@ -0,0 +1,12 @@
+# DP: suggest installation of python3-gdbm package on failing _gdbm import
+
+--- a/Lib/dbm/gnu.py
++++ b/Lib/dbm/gnu.py
+@@ -1,3 +1,6 @@
+ """Provide the _gdbm module as a dbm submodule."""
+
+-from _gdbm import *
++try:
++ from _gdbm import *
++except ImportError as msg:
++ raise ImportError(str(msg) + ', please install the python3-gdbm package')
diff --git a/debian/patches/git-updates.diff b/debian/patches/git-updates.diff
new file mode 100644
index 0000000..f9229ee
--- /dev/null
+++ b/debian/patches/git-updates.diff
@@ -0,0 +1,4 @@
+# DP: updates from the 3.6 branch (until 2017-06-07, ).
+
+# git diff 69c0db5050f623e8895b72dfe970392b1f9a0e2e 09b6c0c71ea944f7e8b46998f3ebaf5b9fbe15f6 | filterdiff -x ?/.hgignore -x ?/.hgeol -x ?/.hgtags -x ?/.hgtouch -x ?/.gitignore -x ?/.gitattributes -x '?/.github/*' -x '?/.git*' -x ?/.codecov.yml -x ?/.travis.yml -x ?/configure --remove-timestamps
+
diff --git a/debian/patches/langpack-gettext.diff b/debian/patches/langpack-gettext.diff
new file mode 100644
index 0000000..56deb77
--- /dev/null
+++ b/debian/patches/langpack-gettext.diff
@@ -0,0 +1,36 @@
+# DP: Description: support alternative gettext tree in
+# DP: /usr/share/locale-langpack; if a file is present in both trees,
+# DP: prefer the newer one
+# DP: Upstream status: Ubuntu-Specific
+
+Index: b/Lib/gettext.py
+===================================================================
+--- a/Lib/gettext.py
++++ b/Lib/gettext.py
+@@ -491,11 +491,26 @@ def find(domain, localedir=None, languag
+ if lang == 'C':
+ break
+ mofile = os.path.join(localedir, lang, 'LC_MESSAGES', '%s.mo' % domain)
++ mofile_lp = os.path.join("/usr/share/locale-langpack", lang,
++ 'LC_MESSAGES', '%s.mo' % domain)
++
++ # first look into the standard locale dir, then into the
++ # langpack locale dir
++
++ # standard mo file
+ if os.path.exists(mofile):
+ if all:
+ result.append(mofile)
+ else:
+ return mofile
++
++ # langpack mofile -> use it
++ if os.path.exists(mofile_lp):
++ if all:
++ result.append(mofile_lp)
++ else:
++ return mofile_lp
++
+ return result
+
+
diff --git a/debian/patches/lib-argparse.diff b/debian/patches/lib-argparse.diff
new file mode 100644
index 0000000..c9d604a
--- /dev/null
+++ b/debian/patches/lib-argparse.diff
@@ -0,0 +1,22 @@
+# DP: argparse.py: Make the gettext import conditional
+
+--- a/Lib/argparse.py
++++ b/Lib/argparse.py
+@@ -90,7 +90,16 @@
+ import sys as _sys
+ import textwrap as _textwrap
+
+-from gettext import gettext as _, ngettext
++try:
++ from gettext import gettext as _, ngettext
++except ImportError:
++ def _(message):
++ return message
++ def ngettext(singular,plural,n):
++ if n == 1:
++ return singular
++ else:
++ return plural
+
+
+ SUPPRESS = '==SUPPRESS=='
diff --git a/debian/patches/lib2to3-no-pickled-grammar.diff b/debian/patches/lib2to3-no-pickled-grammar.diff
new file mode 100644
index 0000000..6364384
--- /dev/null
+++ b/debian/patches/lib2to3-no-pickled-grammar.diff
@@ -0,0 +1,92 @@
+Index: b/Lib/lib2to3/pgen2/driver.py
+===================================================================
+--- a/Lib/lib2to3/pgen2/driver.py
++++ b/Lib/lib2to3/pgen2/driver.py
+@@ -122,7 +122,10 @@ def load_grammar(gt="Grammar.txt", gp=No
+ if force or not _newer(gp, gt):
+ logger.info("Generating grammar tables from %s", gt)
+ g = pgen.generate_grammar(gt)
+- if save:
++ # the pickle files mismatch, when built on different architectures.
++ # don't save these for now. An alternative solution might be to
++ # include the multiarch triplet into the file name
++ if False:
+ logger.info("Writing grammar tables to %s", gp)
+ try:
+ g.dump(gp)
+Index: b/Lib/lib2to3/tests/test_parser.py
+===================================================================
+--- a/Lib/lib2to3/tests/test_parser.py
++++ b/Lib/lib2to3/tests/test_parser.py
+@@ -36,71 +36,6 @@
+ self.assertEqual(t.children[1].children[0].type, syms.print_stmt)
+
+
+-class TestPgen2Caching(support.TestCase):
+- def test_load_grammar_from_txt_file(self):
+- pgen2_driver.load_grammar(support.grammar_path, save=False, force=True)
+-
+- def test_load_grammar_from_pickle(self):
+- # Make a copy of the grammar file in a temp directory we are
+- # guaranteed to be able to write to.
+- tmpdir = tempfile.mkdtemp()
+- try:
+- grammar_copy = os.path.join(
+- tmpdir, os.path.basename(support.grammar_path))
+- shutil.copy(support.grammar_path, grammar_copy)
+- pickle_name = pgen2_driver._generate_pickle_name(grammar_copy)
+-
+- pgen2_driver.load_grammar(grammar_copy, save=True, force=True)
+- self.assertTrue(os.path.exists(pickle_name))
+-
+- os.unlink(grammar_copy) # Only the pickle remains...
+- pgen2_driver.load_grammar(grammar_copy, save=False, force=False)
+- finally:
+- shutil.rmtree(tmpdir)
+-
+- @unittest.skipIf(sys.executable is None, 'sys.executable required')
+- def test_load_grammar_from_subprocess(self):
+- tmpdir = tempfile.mkdtemp()
+- tmpsubdir = os.path.join(tmpdir, 'subdir')
+- try:
+- os.mkdir(tmpsubdir)
+- grammar_base = os.path.basename(support.grammar_path)
+- grammar_copy = os.path.join(tmpdir, grammar_base)
+- grammar_sub_copy = os.path.join(tmpsubdir, grammar_base)
+- shutil.copy(support.grammar_path, grammar_copy)
+- shutil.copy(support.grammar_path, grammar_sub_copy)
+- pickle_name = pgen2_driver._generate_pickle_name(grammar_copy)
+- pickle_sub_name = pgen2_driver._generate_pickle_name(
+- grammar_sub_copy)
+- self.assertNotEqual(pickle_name, pickle_sub_name)
+-
+- # Generate a pickle file from this process.
+- pgen2_driver.load_grammar(grammar_copy, save=True, force=True)
+- self.assertTrue(os.path.exists(pickle_name))
+-
+- # Generate a new pickle file in a subprocess with a most likely
+- # different hash randomization seed.
+- sub_env = dict(os.environ)
+- sub_env['PYTHONHASHSEED'] = 'random'
+- subprocess.check_call(
+- [sys.executable, '-c', """
+-from lib2to3.pgen2 import driver as pgen2_driver
+-pgen2_driver.load_grammar(%r, save=True, force=True)
+- """ % (grammar_sub_copy,)],
+- env=sub_env)
+- self.assertTrue(os.path.exists(pickle_sub_name))
+-
+- with open(pickle_name, 'rb') as pickle_f_1, \
+- open(pickle_sub_name, 'rb') as pickle_f_2:
+- self.assertEqual(
+- pickle_f_1.read(), pickle_f_2.read(),
+- msg='Grammar caches generated using different hash seeds'
+- ' were not identical.')
+- finally:
+- shutil.rmtree(tmpdir)
+-
+-
+-
+ class GrammarTest(support.TestCase):
+ def validate(self, code):
+ support.parse_string(code)
diff --git a/debian/patches/link-opt.diff b/debian/patches/link-opt.diff
new file mode 100644
index 0000000..4b4d7b7
--- /dev/null
+++ b/debian/patches/link-opt.diff
@@ -0,0 +1,26 @@
+# DP: Call the linker with -O1 -Bsymbolic-functions
+
+Index: b/configure.ac
+===================================================================
+--- a/configure.ac
++++ b/configure.ac
+@@ -2511,8 +2511,8 @@ then
+ fi
+ ;;
+ Linux*|GNU*|QNX*)
+- LDSHARED='$(CC) -shared'
+- LDCXXSHARED='$(CXX) -shared';;
++ LDSHARED='$(CC) -shared -Wl,-O1 -Wl,-Bsymbolic-functions'
++ LDCXXSHARED='$(CXX) -shared -Wl,-O1 -Wl,-Bsymbolic-functions';;
+ BSD/OS*/4*)
+ LDSHARED="gcc -shared"
+ LDCXXSHARED="g++ -shared";;
+@@ -2612,7 +2612,7 @@ then
+ # LINKFORSHARED="-Wl,-E -Wl,+s -Wl,+b\$(BINLIBDEST)/lib-dynload";;
+ BSD/OS/4*) LINKFORSHARED="-Xlinker -export-dynamic";;
+ Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";;
+- Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";;
++ Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions";;
+ # -u libsys_s pulls in all symbols in libsys
+ Darwin/*)
+ LINKFORSHARED="$extra_undefs -framework CoreFoundation"
diff --git a/debian/patches/link-timemodule.diff b/debian/patches/link-timemodule.diff
new file mode 100644
index 0000000..45e4153
--- /dev/null
+++ b/debian/patches/link-timemodule.diff
@@ -0,0 +1,13 @@
+Index: b/Modules/Setup.dist
+===================================================================
+--- a/Modules/Setup.dist
++++ b/Modules/Setup.dist
+@@ -118,7 +118,7 @@ _collections _collectionsmodule.c # Cont
+ itertools itertoolsmodule.c # Functions creating iterators for efficient looping
+ atexit atexitmodule.c # Register functions to be run at interpreter-shutdown
+ _stat _stat.c # stat.h interface
+-time timemodule.c # -lm # time operations and variables
++time timemodule.c -lrt # -lm # time operations and variables
+
+ # access to ISO C locale support
+ _locale _localemodule.c # -lintl
diff --git a/debian/patches/locale-module.diff b/debian/patches/locale-module.diff
new file mode 100644
index 0000000..76fd849
--- /dev/null
+++ b/debian/patches/locale-module.diff
@@ -0,0 +1,19 @@
+# DP: * Lib/locale.py:
+# DP: - Don't map 'utf8', 'utf-8' to 'utf', which is not a known encoding
+# DP: for glibc.
+
+Index: b/Lib/locale.py
+===================================================================
+--- a/Lib/locale.py
++++ b/Lib/locale.py
+@@ -1339,8 +1339,8 @@ locale_alias = {
+ 'ug_cn': 'ug_CN.UTF-8',
+ 'uk': 'uk_UA.KOI8-U',
+ 'uk_ua': 'uk_UA.KOI8-U',
+- 'univ': 'en_US.utf',
+- 'universal': 'en_US.utf',
++ 'univ': 'en_US.UTF-8',
++ 'universal': 'en_US.UTF-8',
+ 'universal.utf8@ucs4': 'en_US.UTF-8',
+ 'unm_us': 'unm_US.UTF-8',
+ 'ur': 'ur_PK.CP1256',
diff --git a/debian/patches/lto-link-flags.diff b/debian/patches/lto-link-flags.diff
new file mode 100644
index 0000000..afea9c2
--- /dev/null
+++ b/debian/patches/lto-link-flags.diff
@@ -0,0 +1,22 @@
+Index: b/Makefile.pre.in
+===================================================================
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -146,7 +146,7 @@ CONFINCLUDEPY= $(CONFINCLUDEDIR)/python$
+ SHLIB_SUFFIX= @SHLIB_SUFFIX@
+ EXT_SUFFIX= @EXT_SUFFIX@
+ LDSHARED= @LDSHARED@ $(PY_LDFLAGS)
+-BLDSHARED= @BLDSHARED@ $(PY_LDFLAGS)
++BLDSHARED= @BLDSHARED@ $(PY_LDFLAGS) $(PY_CFLAGS)
+ LDCXXSHARED= @LDCXXSHARED@
+ DESTSHARED= $(BINLIBDEST)/lib-dynload
+
+@@ -544,7 +544,7 @@ clinic: $(BUILDPYTHON) $(srcdir)/Modules
+
+ # Build the interpreter
+ $(BUILDPYTHON): Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY)
+- $(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
++ $(LINKCC) $(PY_LDFLAGS) $(PY_CFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
+
+ platform: $(BUILDPYTHON) pybuilddir.txt
+ $(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print("%s-%d.%d" % (get_platform(), *sys.version_info[:2]))' >platform
diff --git a/debian/patches/mangle-fstack-protector.diff b/debian/patches/mangle-fstack-protector.diff
new file mode 100644
index 0000000..19b27f7
--- /dev/null
+++ b/debian/patches/mangle-fstack-protector.diff
@@ -0,0 +1,26 @@
+# DP: When using GCC versions older than 4.9, automagically mangle
+# DP: -fstack-protector-strong to -fstack-protector
+
+Index: b/Lib/distutils/sysconfig.py
+===================================================================
+--- a/Lib/distutils/sysconfig.py
++++ b/Lib/distutils/sysconfig.py
+@@ -13,6 +13,7 @@ import _imp
+ import os
+ import re
+ import sys
++import fnmatch
+
+ from .errors import DistutilsPlatformError
+
+@@ -197,6 +198,10 @@ def customize_compiler(compiler):
+ cc = newcc
+ if 'CXX' in os.environ:
+ cxx = os.environ['CXX']
++ if fnmatch.filter([cc, cxx], '*-4.[0-8]'):
++ configure_cflags = configure_cflags.replace('-fstack-protector-strong', '-fstack-protector')
++ ldshared = ldshared.replace('-fstack-protector-strong', '-fstack-protector')
++ cflags = cflags.replace('-fstack-protector-strong', '-fstack-protector')
+ if 'LDSHARED' in os.environ:
+ ldshared = os.environ['LDSHARED']
+ if 'CPP' in os.environ:
diff --git a/debian/patches/multiarch-extname.diff b/debian/patches/multiarch-extname.diff
new file mode 100644
index 0000000..1ab825d
--- /dev/null
+++ b/debian/patches/multiarch-extname.diff
@@ -0,0 +1,92 @@
+# DP: Make sure to rename extensions to a tag including the MULTIARCH name
+
+this patch can be dropped for python3.5 final, if the upstream chage is kept.
+
+Index: b/Lib/distutils/dir_util.py
+===================================================================
+--- a/Lib/distutils/dir_util.py
++++ b/Lib/distutils/dir_util.py
+@@ -96,6 +96,9 @@ def create_tree(base_dir, files, mode=0o
+ for dir in sorted(need_dir):
+ mkpath(dir, mode, verbose=verbose, dry_run=dry_run)
+
++import sysconfig
++_multiarch = None
++
+ def copy_tree(src, dst, preserve_mode=1, preserve_times=1,
+ preserve_symlinks=0, update=0, verbose=1, dry_run=0):
+ """Copy an entire directory tree 'src' to a new location 'dst'.
+@@ -131,6 +134,13 @@ def copy_tree(src, dst, preserve_mode=1,
+ raise DistutilsFileError(
+ "error listing files in '%s': %s" % (src, e.strerror))
+
++ ext_suffix = sysconfig.get_config_var ('EXT_SUFFIX')
++ _multiarch = sysconfig.get_config_var ('MULTIARCH')
++ if ext_suffix.endswith(_multiarch + ext_suffix[-3:]):
++ new_suffix = None
++ else:
++ new_suffix = "%s-%s%s" % (ext_suffix[:-3], _multiarch, ext_suffix[-3:])
++
+ if not dry_run:
+ mkpath(dst, verbose=verbose)
+
+@@ -139,6 +149,9 @@ def copy_tree(src, dst, preserve_mode=1,
+ for n in names:
+ src_name = os.path.join(src, n)
+ dst_name = os.path.join(dst, n)
++ if new_suffix and _multiarch and n.endswith(ext_suffix) and not n.endswith(new_suffix):
++ dst_name = os.path.join(dst, n.replace(ext_suffix, new_suffix))
++ log.info("renaming extension %s -> %s", n, n.replace(ext_suffix, new_suffix))
+
+ if n.startswith('.nfs'):
+ # skip NFS rename files
+Index: b/Lib/distutils/command/install_lib.py
+===================================================================
+--- a/Lib/distutils/command/install_lib.py
++++ b/Lib/distutils/command/install_lib.py
+@@ -56,6 +56,7 @@ class install_lib(Command):
+ self.compile = None
+ self.optimize = None
+ self.skip_build = None
++ self.multiarch = None # if we should rename the extensions
+
+ def finalize_options(self):
+ # Get all the information we need to install pure Python modules
+@@ -68,6 +69,7 @@ class install_lib(Command):
+ ('compile', 'compile'),
+ ('optimize', 'optimize'),
+ ('skip_build', 'skip_build'),
++ ('multiarch', 'multiarch'),
+ )
+
+ if self.compile is None:
+@@ -108,6 +110,8 @@ class install_lib(Command):
+
+ def install(self):
+ if os.path.isdir(self.build_dir):
++ import distutils.dir_util
++ distutils.dir_util._multiarch = self.multiarch
+ outfiles = self.copy_tree(self.build_dir, self.install_dir)
+ else:
+ self.warn("'%s' does not exist -- no Python modules to install" %
+Index: b/Lib/distutils/command/install.py
+===================================================================
+--- a/Lib/distutils/command/install.py
++++ b/Lib/distutils/command/install.py
+@@ -192,6 +192,7 @@ class install(Command):
+
+ # enable custom installation, known values: deb
+ self.install_layout = None
++ self.multiarch = None
+
+ self.compile = None
+ self.optimize = None
+@@ -451,6 +452,8 @@ class install(Command):
+ self.install_platbase = self.exec_prefix
+ if self.install_layout:
+ if self.install_layout.lower() in ['deb']:
++ import sysconfig
++ self.multiarch = sysconfig.get_config_var('MULTIARCH')
+ self.select_scheme("deb_system")
+ elif self.install_layout.lower() in ['unix']:
+ self.select_scheme("unix_prefix")
diff --git a/debian/patches/multiarch.diff b/debian/patches/multiarch.diff
new file mode 100644
index 0000000..dace3f5
--- /dev/null
+++ b/debian/patches/multiarch.diff
@@ -0,0 +1,52 @@
+Index: b/Lib/sysconfig.py
+===================================================================
+--- a/Lib/sysconfig.py
++++ b/Lib/sysconfig.py
+@@ -557,6 +557,12 @@ def get_config_vars(*args):
+ # the init-function.
+ _CONFIG_VARS['userbase'] = _getuserbase()
+
++ multiarch = get_config_var('MULTIARCH')
++ if multiarch:
++ _CONFIG_VARS['multiarchsubdir'] = '/' + multiarch
++ else:
++ _CONFIG_VARS['multiarchsubdir'] = ''
++
+ # Always convert srcdir to an absolute path
+ srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
+ if os.name == 'posix':
+Index: b/Lib/distutils/sysconfig.py
+===================================================================
+--- a/Lib/distutils/sysconfig.py
++++ b/Lib/distutils/sysconfig.py
+@@ -99,6 +99,9 @@ def get_python_inc(plat_specific=0, pref
+ incdir = os.path.join(get_config_var('srcdir'), 'Include')
+ return os.path.normpath(incdir)
+ python_dir = 'python' + get_python_version() + build_flags
++ if not python_build and plat_specific:
++ import sysconfig
++ return sysconfig.get_path('platinclude')
+ return os.path.join(prefix, "include", python_dir)
+ elif os.name == "nt":
+ return os.path.join(prefix, "include")
+Index: b/Makefile.pre.in
+===================================================================
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -760,6 +760,7 @@ Modules/signalmodule.o: $(srcdir)/Module
+
+ Python/dynload_shlib.o: $(srcdir)/Python/dynload_shlib.c Makefile
+ $(CC) -c $(PY_CORE_CFLAGS) \
++ $(if $(MULTIARCH),-DMULTIARCH='"$(MULTIARCH)"') \
+ -DSOABI='"$(SOABI)"' \
+ -o $@ $(srcdir)/Python/dynload_shlib.c
+
+@@ -1404,7 +1405,7 @@ inclinstall:
+ LIBPL= @LIBPL@
+
+ # pkgconfig directory
+-LIBPC= $(LIBDIR)/pkgconfig
++LIBPC= $(LIBDIR)/$(MULTIARCH)/pkgconfig
+
+ libainstall: @DEF_MAKE_RULE@ python-config
+ @for i in $(LIBDIR) $(LIBPL) $(LIBPC); \
diff --git a/debian/patches/platform-lsbrelease.diff b/debian/patches/platform-lsbrelease.diff
new file mode 100644
index 0000000..271139f
--- /dev/null
+++ b/debian/patches/platform-lsbrelease.diff
@@ -0,0 +1,65 @@
+# DP: Use /etc/lsb-release to identify the platform.
+
+Index: b/Lib/platform.py
+===================================================================
+--- a/Lib/platform.py
++++ b/Lib/platform.py
+@@ -267,7 +267,7 @@ _release_version = re.compile(r'([^0-9]+
+ _supported_dists = (
+ 'SuSE', 'debian', 'fedora', 'redhat', 'centos',
+ 'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
+- 'UnitedLinux', 'turbolinux', 'arch', 'mageia')
++ 'UnitedLinux', 'turbolinux', 'arch', 'mageia', 'Ubuntu')
+
+ def _parse_release_file(firstline):
+
+@@ -296,6 +296,10 @@ def _parse_release_file(firstline):
+ id = l[1]
+ return '', version, id
+
++_distributor_id_file_re = re.compile("(?:DISTRIB_ID\s*=)\s*(.*)", re.I)
++_release_file_re = re.compile("(?:DISTRIB_RELEASE\s*=)\s*(.*)", re.I)
++_codename_file_re = re.compile("(?:DISTRIB_CODENAME\s*=)\s*(.*)", re.I)
++
+ def linux_distribution(distname='', version='', id='',
+
+ supported_dists=_supported_dists,
+@@ -328,6 +332,25 @@ def _linux_distribution(distname, versio
+ args given as parameters.
+
+ """
++ # check for the Debian/Ubuntu /etc/lsb-release file first, needed so
++ # that the distribution doesn't get identified as Debian.
++ try:
++ with open("/etc/lsb-release", "r") as etclsbrel:
++ for line in etclsbrel:
++ m = _distributor_id_file_re.search(line)
++ if m:
++ _u_distname = m.group(1).strip()
++ m = _release_file_re.search(line)
++ if m:
++ _u_version = m.group(1).strip()
++ m = _codename_file_re.search(line)
++ if m:
++ _u_id = m.group(1).strip()
++ if _u_distname and _u_version:
++ return (_u_distname, _u_version, _u_id)
++ except (EnvironmentError, UnboundLocalError):
++ pass
++
+ try:
+ etc = os.listdir(_UNIXCONFDIR)
+ except OSError:
+Index: b/Lib/test/test_platform.py
+===================================================================
+--- a/Lib/test/test_platform.py
++++ b/Lib/test/test_platform.py
+@@ -349,6 +349,8 @@ class PlatformTest(unittest.TestCase):
+ self.assertEqual(version, '19')
+ self.assertEqual(distid, 'Schr\xf6dinger\u2019s Cat')
+
++ # we know we are Debian/Ubuntu
++ test_linux_distribution_encoding.skip = True
+
+ class DeprecationTest(unittest.TestCase):
+
diff --git a/debian/patches/profiled-build.diff b/debian/patches/profiled-build.diff
new file mode 100644
index 0000000..1eb203b
--- /dev/null
+++ b/debian/patches/profiled-build.diff
@@ -0,0 +1,23 @@
+# DP: Ignore errors in the profile task.
+
+Index: b/Makefile.pre.in
+===================================================================
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -467,6 +467,16 @@ build_all_generate_profile:
+ run_profile_task:
+ : # FIXME: can't run for a cross build
+ $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $(PROFILE_TASK) || true
++ task="$(PROFILE_TASK)"; \
++ case "$$task" in \
++ *-s\ *) \
++ $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $$task; \
++ while [ -f $(srcdir)/build/pynexttest ]; do \
++ $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $$task; \
++ done;; \
++ *) \
++ $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $$task; \
++ esac
+
+ build_all_merge_profile:
+ $(LLVM_PROF_MERGER)
diff --git a/debian/patches/pydoc-use-pager.diff b/debian/patches/pydoc-use-pager.diff
new file mode 100644
index 0000000..a92c245
--- /dev/null
+++ b/debian/patches/pydoc-use-pager.diff
@@ -0,0 +1,15 @@
+# DP: pydoc: use the pager command if available.
+
+Index: b/Lib/pydoc.py
+===================================================================
+--- a/Lib/pydoc.py
++++ b/Lib/pydoc.py
+@@ -1446,6 +1446,8 @@ def getpager():
+ return plainpager
+ if sys.platform == 'win32':
+ return lambda text: tempfilepager(plain(text), 'more <')
++ if hasattr(os, 'system') and os.system('(pager) 2>/dev/null') == 0:
++ return lambda text: pipepager(text, 'pager')
+ if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
+ return lambda text: pipepager(text, 'less')
+
diff --git a/debian/patches/pyhash.diff b/debian/patches/pyhash.diff
new file mode 100644
index 0000000..f8ecfda
--- /dev/null
+++ b/debian/patches/pyhash.diff
@@ -0,0 +1,67 @@
+Index: b/Python/pyhash.c
+===================================================================
+--- a/Python/pyhash.c
++++ b/Python/pyhash.c
+@@ -328,13 +328,14 @@ static PyHash_FuncDef PyHash_Func = {fnv
+ * the hash values' least significant bits.
+ */
+ #if PY_LITTLE_ENDIAN
+-# define _le64toh(x) ((uint64_t)(x))
++# define _le64toh(v, x) memcpy(&(v), &(x), sizeof(v))
+ #elif defined(__APPLE__)
+-# define _le64toh(x) OSSwapLittleToHostInt64(x)
++# define _le64toh(v, x) v = OSSwapLittleToHostInt64(x)
+ #elif defined(HAVE_LETOH64)
+-# define _le64toh(x) le64toh(x)
++# define _le64toh(v, x) v = le64toh(x)
+ #else
+-# define _le64toh(x) (((uint64_t)(x) << 56) | \
++# define _le64toh(v, x) v = \
++ (((uint64_t)(x) << 56) | \
+ (((uint64_t)(x) << 40) & 0xff000000000000ULL) | \
+ (((uint64_t)(x) << 24) & 0xff0000000000ULL) | \
+ (((uint64_t)(x) << 8) & 0xff00000000ULL) | \
+@@ -366,22 +367,24 @@ static PyHash_FuncDef PyHash_Func = {fnv
+
+ static Py_hash_t
+ siphash24(const void *src, Py_ssize_t src_sz) {
+- uint64_t k0 = _le64toh(_Py_HashSecret.siphash.k0);
+- uint64_t k1 = _le64toh(_Py_HashSecret.siphash.k1);
++ uint64_t k0, k1, v0, v1, v2, v3;
+ uint64_t b = (uint64_t)src_sz << 56;
+ const uint64_t *in = (uint64_t*)src;
+
+- uint64_t v0 = k0 ^ 0x736f6d6570736575ULL;
+- uint64_t v1 = k1 ^ 0x646f72616e646f6dULL;
+- uint64_t v2 = k0 ^ 0x6c7967656e657261ULL;
+- uint64_t v3 = k1 ^ 0x7465646279746573ULL;
+-
+- uint64_t t;
++ uint64_t t, t2;
+ uint8_t *pt;
+ uint8_t *m;
+
++ _le64toh(k0, _Py_HashSecret.siphash.k0);
++ _le64toh(k1, _Py_HashSecret.siphash.k1);
++ v0 = k0 ^ 0x736f6d6570736575ULL;
++ v1 = k1 ^ 0x646f72616e646f6dULL;
++ v2 = k0 ^ 0x6c7967656e657261ULL;
++ v3 = k1 ^ 0x7465646279746573ULL;
++
+ while (src_sz >= 8) {
+- uint64_t mi = _le64toh(*in);
++ uint64_t mi;
++ _le64toh(mi, *in);
+ in += 1;
+ src_sz -= 8;
+ v3 ^= mi;
+@@ -401,7 +404,8 @@ siphash24(const void *src, Py_ssize_t sr
+ case 2: pt[1] = m[1]; /* fall through */
+ case 1: pt[0] = m[0]; /* fall through */
+ }
+- b |= _le64toh(t);
++ _le64toh(t2, t);
++ b |= t2;
+
+ v3 ^= b;
+ DOUBLE_ROUND(v0,v1,v2,v3);
diff --git a/debian/patches/reproducible-buildinfo.diff b/debian/patches/reproducible-buildinfo.diff
new file mode 100644
index 0000000..232e43e
--- /dev/null
+++ b/debian/patches/reproducible-buildinfo.diff
@@ -0,0 +1,15 @@
+# DP: Build getbuildinfo.o with DATE/TIME values when defined
+
+Index: b/Makefile.pre.in
+===================================================================
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -732,6 +732,8 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \
+ -DGITVERSION="\"`LC_ALL=C $(GITVERSION)`\"" \
+ -DGITTAG="\"`LC_ALL=C $(GITTAG)`\"" \
+ -DGITBRANCH="\"`LC_ALL=C $(GITBRANCH)`\"" \
++ $(if $(BUILD_DATE),-DDATE='"$(BUILD_DATE)"') \
++ $(if $(BUILD_TIME),-DTIME='"$(BUILD_TIME)"') \
+ -o $@ $(srcdir)/Modules/getbuildinfo.c
+
+ Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..9eed915
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,34 @@
+# git-updates.diff
+deb-setup.diff
+deb-locations.diff
+distutils-install-layout.diff
+locale-module.diff
+distutils-link.diff
+distutils-sysconfig.diff
+tkinter-import.diff
+gdbm-import.diff
+link-opt.diff
+setup-modules.diff
+platform-lsbrelease.diff
+bdist-wininst-notfound.diff
+profiled-build.diff
+langpack-gettext.diff
+disable-sem-check.diff
+lib-argparse.diff
+ctypes-arm.diff
+# link-timemodule.diff
+lto-link-flags.diff
+multiarch.diff
+lib2to3-no-pickled-grammar.diff
+ext-no-libpython-link.diff
+test-no-random-order.diff
+multiarch-extname.diff
+tempfile-minimal.diff
+disable-some-tests.diff
+ensurepip-wheels.diff
+ensurepip-disabled.diff
+mangle-fstack-protector.diff
+reproducible-buildinfo.diff
+pydoc-use-pager.diff
+pyhash.diff
+update-tls-protocol.diff
diff --git a/debian/patches/setup-modules.diff b/debian/patches/setup-modules.diff
new file mode 100644
index 0000000..8c10c06
--- /dev/null
+++ b/debian/patches/setup-modules.diff
@@ -0,0 +1,52 @@
+# DP: Modules/Setup.dist: patches to build some extensions statically
+
+Index: b/Modules/Setup.dist
+===================================================================
+--- a/Modules/Setup.dist
++++ b/Modules/Setup.dist
+@@ -176,7 +176,7 @@ _symtable symtablemodule.c
+ #_weakref _weakref.c # basic weak reference support
+ #_testcapi _testcapimodule.c # Python C API test module
+ #_random _randommodule.c # Random number generator
+-#_elementtree -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI _elementtree.c # elementtree accelerator
++#_elementtree _elementtree.c -lexpat # elementtree accelerator
+ #_pickle _pickle.c # pickle accelerator
+ #_datetime _datetimemodule.c # datetime accelerator
+ #_bisect _bisectmodule.c # Bisection algorithms
+@@ -206,10 +206,7 @@ _symtable symtablemodule.c
+
+ # Socket module helper for SSL support; you must comment out the other
+ # socket line above, and possibly edit the SSL variable:
+-#SSL=/usr/local/ssl
+-#_ssl _ssl.c \
+-# -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
+-# -L$(SSL)/lib -lssl -lcrypto
++#_ssl _ssl.c -lssl -lcrypto
+
+ # The crypt module is now disabled by default because it breaks builds
+ # on many systems (where -lcrypt is needed), e.g. Linux (I believe).
+@@ -244,6 +241,7 @@ _symtable symtablemodule.c
+
+ #_md5 md5module.c
+
++#_hashlib _hashopenssl.c -lssl -lcrypto
+
+ # The _sha module implements the SHA checksum algorithms.
+ # (NIST's Secure Hash Algorithms.)
+@@ -342,6 +340,7 @@ _symtable symtablemodule.c
+ # Fred Drake's interface to the Python parser
+ #parser parsermodule.c
+
++#_ctypes _ctypes/_ctypes.c _ctypes/callbacks.c _ctypes/callproc.c _ctypes/stgdict.c _ctypes/cfield.c _ctypes/malloc_closure.c -lffi
+
+ # Lee Busby's SIGFPE modules.
+ # The library to link fpectl with is platform specific.
+@@ -376,7 +375,7 @@ _symtable symtablemodule.c
+ #
+ # More information on Expat can be found at www.libexpat.org.
+ #
+-#pyexpat expat/xmlparse.c expat/xmlrole.c expat/xmltok.c pyexpat.c -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI
++#pyexpat pyexpat.c -lexpat
+
+ # Hye-Shik Chang's CJKCodecs
+
diff --git a/debian/patches/sysconfig-debian-schemes.diff b/debian/patches/sysconfig-debian-schemes.diff
new file mode 100644
index 0000000..d26ee20
--- /dev/null
+++ b/debian/patches/sysconfig-debian-schemes.diff
@@ -0,0 +1,67 @@
+# DP: Add schemes 'deb_system' and 'posix_local', make the latter the default
+
+--- a/Lib/sysconfig.py
++++ b/Lib/sysconfig.py
+@@ -32,6 +32,30 @@
+ 'scripts': '{base}/bin',
+ 'data': '{base}',
+ },
++ 'deb_system': {
++ 'stdlib': '{installed_base}/lib/python{py_version_short}',
++ 'platstdlib': '{platbase}/lib/python{py_version_short}',
++ 'purelib': '{base}/lib/python3/dist-packages',
++ 'platlib': '{platbase}/lib/python3/dist-packages',
++ 'include':
++ '{installed_base}/include/python{py_version_short}{abiflags}',
++ 'platinclude':
++ '{installed_platbase}/include/python{py_version_short}{abiflags}',
++ 'scripts': '{base}/bin',
++ 'data': '{base}',
++ },
++ 'posix_local': {
++ 'stdlib': '{installed_base}/lib/python{py_version_short}',
++ 'platstdlib': '{platbase}/lib/python{py_version_short}',
++ 'purelib': '{base}/local/lib/python{py_version_short}/dist-packages',
++ 'platlib': '{platbase}/local/lib/python{py_version_short}/dist-packages',
++ 'include':
++ '{installed_base}/local/include/python{py_version_short}{abiflags}',
++ 'platinclude':
++ '{installed_platbase}/local/include/python{py_version_short}{abiflags}',
++ 'scripts': '{base}/local/bin',
++ 'data': '{base}',
++ },
+ 'posix_home': {
+ 'stdlib': '{installed_base}/lib/python',
+ 'platstdlib': '{base}/lib/python',
+@@ -162,7 +186,7 @@
+ _PYTHON_BUILD = is_python_build(True)
+
+ if _PYTHON_BUILD:
+- for scheme in ('posix_prefix', 'posix_home'):
++ for scheme in ('posix_prefix', 'posix_home', 'posix_local', 'deb_system'):
+ _INSTALL_SCHEMES[scheme]['include'] = '{srcdir}/Include'
+ _INSTALL_SCHEMES[scheme]['platinclude'] = '{projectbase}/.'
+
+@@ -200,7 +224,12 @@
+ def _get_default_scheme():
+ if os.name == 'posix':
+ # the default scheme for posix is posix_prefix
+- return 'posix_prefix'
++ if 'real_prefix' in sys.__dict__ or 'VIRTUAL_ENV' in os.environ:
++ # virtual environments
++ return 'posix_prefix'
++ else:
++ # Debian default
++ return 'posix_local'
+ return os.name
+
+
+@@ -485,7 +514,7 @@
+ else:
+ inc_dir = _sys_home or _PROJECT_BASE
+ else:
+- inc_dir = get_path('platinclude')
++ inc_dir = get_path('platinclude', 'posix_prefix')
+ return os.path.join(inc_dir, 'pyconfig.h')
+
+
diff --git a/debian/patches/tempfile-minimal.diff b/debian/patches/tempfile-minimal.diff
new file mode 100644
index 0000000..64f83fc
--- /dev/null
+++ b/debian/patches/tempfile-minimal.diff
@@ -0,0 +1,169 @@
+# DP: Avoid shutil import when it is not available.
+
+Index: b/Lib/tempfile.py
+===================================================================
+--- a/Lib/tempfile.py
++++ b/Lib/tempfile.py
+@@ -40,7 +40,146 @@ import functools as _functools
+ import warnings as _warnings
+ import io as _io
+ import os as _os
+-import shutil as _shutil
++try:
++ import shutil as _shutil
++ _rmtree = _shutil.rmtree
++except ImportError:
++ import sys as _sys
++ import stat as _stat
++ # version vulnerable to race conditions
++ def _rmtree_unsafe(path, onerror):
++ try:
++ if _os.path.islink(path):
++ # symlinks to directories are forbidden, see bug #1669
++ raise OSError("Cannot call rmtree on a symbolic link")
++ except OSError:
++ onerror(_os.path.islink, path, _sys.exc_info())
++ # can't continue even if onerror hook returns
++ return
++ names = []
++ try:
++ names = _os.listdir(path)
++ except OSError:
++ onerror(_os.listdir, path, _sys.exc_info())
++ for name in names:
++ fullname = _os.path.join(path, name)
++ try:
++ mode = _os.lstat(fullname).st_mode
++ except OSError:
++ mode = 0
++ if _stat.S_ISDIR(mode):
++ _rmtree_unsafe(fullname, onerror)
++ else:
++ try:
++ _os.unlink(fullname)
++ except OSError:
++ onerror(_os.unlink, fullname, _sys.exc_info())
++ try:
++ _os.rmdir(path)
++ except OSError:
++ onerror(_os.rmdir, path, _sys.exc_info())
++
++ # Version using fd-based APIs to protect against races
++ def _rmtree_safe_fd(topfd, path, onerror):
++ names = []
++ try:
++ names = _os.listdir(topfd)
++ except OSError as err:
++ err.filename = path
++ onerror(_os.listdir, path, _sys.exc_info())
++ for name in names:
++ fullname = _os.path.join(path, name)
++ try:
++ orig_st = _os.stat(name, dir_fd=topfd, follow_symlinks=False)
++ mode = orig_st.st_mode
++ except OSError:
++ mode = 0
++ if _stat.S_ISDIR(mode):
++ try:
++ dirfd = _os.open(name, _os.O_RDONLY, dir_fd=topfd)
++ except OSError:
++ onerror(_os.open, fullname, _sys.exc_info())
++ else:
++ try:
++ if _os.path.samestat(orig_st, _os.fstat(dirfd)):
++ _rmtree_safe_fd(dirfd, fullname, onerror)
++ try:
++ _os.rmdir(name, dir_fd=topfd)
++ except OSError:
++ onerror(_os.rmdir, fullname, _sys.exc_info())
++ else:
++ try:
++ # This can only happen if someone replaces
++ # a directory with a symlink after the call to
++ # stat.S_ISDIR above.
++ raise OSError("Cannot call rmtree on a symbolic "
++ "link")
++ except OSError:
++ onerror(_os.path.islink, fullname, _sys.exc_info())
++ finally:
++ _os.close(dirfd)
++ else:
++ try:
++ _os.unlink(name, dir_fd=topfd)
++ except OSError:
++ onerror(_os.unlink, fullname, _sys.exc_info())
++
++ _use_fd_functions = ({_os.open, _os.stat, _os.unlink, _os.rmdir} <=
++ _os.supports_dir_fd and
++ _os.listdir in _os.supports_fd and
++ _os.stat in _os.supports_follow_symlinks)
++
++ def _rmtree(path, ignore_errors=False, onerror=None):
++ """Recursively delete a directory tree.
++
++ If ignore_errors is set, errors are ignored; otherwise, if onerror
++ is set, it is called to handle the error with arguments (func,
++ path, exc_info) where func is platform and implementation dependent;
++ path is the argument to that function that caused it to fail; and
++ exc_info is a tuple returned by sys.exc_info(). If ignore_errors
++ is false and onerror is None, an exception is raised.
++
++ """
++ if ignore_errors:
++ def onerror(*args):
++ pass
++ elif onerror is None:
++ def onerror(*args):
++ raise
++ if _use_fd_functions:
++ # While the unsafe rmtree works fine on bytes, the fd based does not.
++ if isinstance(path, bytes):
++ path = _os.fsdecode(path)
++ # Note: To guard against symlink races, we use the standard
++ # lstat()/open()/fstat() trick.
++ try:
++ orig_st = _os.lstat(path)
++ except Exception:
++ onerror(_os.lstat, path, _sys.exc_info())
++ return
++ try:
++ fd = _os.open(path, _os.O_RDONLY)
++ except Exception:
++ onerror(_os.lstat, path, _sys.exc_info())
++ return
++ try:
++ if _os.path.samestat(orig_st, _os.fstat(fd)):
++ _rmtree_safe_fd(fd, path, onerror)
++ try:
++ _os.rmdir(path)
++ except OSError:
++ onerror(_os.rmdir, path, _sys.exc_info())
++ else:
++ try:
++ # symlinks to directories are forbidden, see bug #1669
++ raise OSError("Cannot call rmtree on a symbolic link")
++ except OSError:
++ onerror(_os.path.islink, path, _sys.exc_info())
++ finally:
++ _os.close(fd)
++ else:
++ return _rmtree_unsafe(path, onerror)
++
+ import errno as _errno
+ from random import Random as _Random
+ import weakref as _weakref
+@@ -794,7 +933,7 @@ class TemporaryDirectory(object):
+
+ @classmethod
+ def _cleanup(cls, name, warn_message):
+- _shutil.rmtree(name)
++ _rmtree(name)
+ _warnings.warn(warn_message, ResourceWarning)
+
+ def __repr__(self):
+@@ -808,4 +947,4 @@ class TemporaryDirectory(object):
+
+ def cleanup(self):
+ if self._finalizer.detach():
+- _shutil.rmtree(self.name)
++ _rmtree(self.name)
diff --git a/debian/patches/test-no-random-order.diff b/debian/patches/test-no-random-order.diff
new file mode 100644
index 0000000..1c98695
--- /dev/null
+++ b/debian/patches/test-no-random-order.diff
@@ -0,0 +1,14 @@
+# DP: Don't run the test suite in random order.
+
+Index: b/Tools/scripts/run_tests.py
+===================================================================
+--- a/Tools/scripts/run_tests.py
++++ b/Tools/scripts/run_tests.py
+@@ -37,7 +37,6 @@ def main(regrtest_args):
+ args.extend(['-W', 'error::BytesWarning'])
+
+ args.extend(['-m', 'test', # Run the test suite
+- '-r', # Randomize test order
+ '-w', # Re-run failed tests in verbose mode
+ ])
+ if sys.platform == 'win32':
diff --git a/debian/patches/tkinter-import.diff b/debian/patches/tkinter-import.diff
new file mode 100644
index 0000000..cd0c42e
--- /dev/null
+++ b/debian/patches/tkinter-import.diff
@@ -0,0 +1,18 @@
+# DP: suggest installation of python-tk package on failing _tkinter import
+
+Index: b/Lib/tkinter/__init__.py
+===================================================================
+--- a/Lib/tkinter/__init__.py
++++ b/Lib/tkinter/__init__.py
+@@ -33,7 +33,10 @@ tk.mainloop()
+ import enum
+ import sys
+
+-import _tkinter # If this fails your Python may not be configured for Tk
++try:
++ import _tkinter
++except ImportError as msg:
++ raise ImportError(str(msg) + ', please install the python3-tk package')
+ TclError = _tkinter.TclError
+ from tkinter.constants import *
+ import re
diff --git a/debian/patches/update-tls-protocol.diff b/debian/patches/update-tls-protocol.diff
new file mode 100644
index 0000000..4548a4a
--- /dev/null
+++ b/debian/patches/update-tls-protocol.diff
@@ -0,0 +1,79 @@
+Index: b/Lib/test/test_ftplib.py
+===================================================================
+--- a/Lib/test/test_ftplib.py
++++ b/Lib/test/test_ftplib.py
+@@ -912,7 +912,7 @@ class TestTLS_FTPClass(TestCase):
+
+ def test_context(self):
+ self.client.quit()
+- ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ self.assertRaises(ValueError, ftplib.FTP_TLS, keyfile=CERTFILE,
+ context=ctx)
+ self.assertRaises(ValueError, ftplib.FTP_TLS, certfile=CERTFILE,
+@@ -941,7 +941,7 @@ class TestTLS_FTPClass(TestCase):
+
+ def test_check_hostname(self):
+ self.client.quit()
+- ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ ctx.verify_mode = ssl.CERT_REQUIRED
+ ctx.check_hostname = True
+ ctx.load_verify_locations(CAFILE)
+Index: b/Lib/test/test_httplib.py
+===================================================================
+--- a/Lib/test/test_httplib.py
++++ b/Lib/test/test_httplib.py
+@@ -1620,7 +1620,7 @@ class HTTPSTest(TestCase):
+ # The (valid) cert validates the HTTP hostname
+ import ssl
+ server = self.make_server(CERT_localhost)
+- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
++ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ context.verify_mode = ssl.CERT_REQUIRED
+ context.load_verify_locations(CERT_localhost)
+ h = client.HTTPSConnection('localhost', server.port, context=context)
+@@ -1634,7 +1634,7 @@ class HTTPSTest(TestCase):
+ # The (valid) cert doesn't validate the HTTP hostname
+ import ssl
+ server = self.make_server(CERT_fakehostname)
+- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
++ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ context.verify_mode = ssl.CERT_REQUIRED
+ context.check_hostname = True
+ context.load_verify_locations(CERT_fakehostname)
+Index: b/Lib/test/test_poplib.py
+===================================================================
+--- a/Lib/test/test_poplib.py
++++ b/Lib/test/test_poplib.py
+@@ -352,7 +352,7 @@ class TestPOP3Class(TestCase):
+ @requires_ssl
+ def test_stls_context(self):
+ expected = b'+OK Begin TLS negotiation'
+- ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ ctx.load_verify_locations(CAFILE)
+ ctx.verify_mode = ssl.CERT_REQUIRED
+ ctx.check_hostname = True
+@@ -392,7 +392,7 @@ class TestPOP3_SSLClass(TestPOP3Class):
+ self.assertIn('POP3_SSL', poplib.__all__)
+
+ def test_context(self):
+- ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ self.assertRaises(ValueError, poplib.POP3_SSL, self.server.host,
+ self.server.port, keyfile=CERTFILE, context=ctx)
+ self.assertRaises(ValueError, poplib.POP3_SSL, self.server.host,
+Index: b/Lib/test/test_urllib2_localnet.py
+===================================================================
+--- a/Lib/test/test_urllib2_localnet.py
++++ b/Lib/test/test_urllib2_localnet.py
+@@ -598,7 +598,7 @@ class TestUrlopen(unittest.TestCase):
+ def cb_sni(ssl_sock, server_name, initial_context):
+ nonlocal sni_name
+ sni_name = server_name
+- context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
++ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ context.set_servername_callback(cb_sni)
+ handler = self.start_https_server(context=context, certfile=CERT_localhost)
+ context = ssl.create_default_context(cafile=CERT_localhost)
diff --git a/debian/patches/update-tls-protocol2.diff b/debian/patches/update-tls-protocol2.diff
new file mode 100644
index 0000000..7dbe9d8
--- /dev/null
+++ b/debian/patches/update-tls-protocol2.diff
@@ -0,0 +1,98 @@
+# Don't apply yet, still test failures ..
+
+Index: b/Lib/test/test_ssl.py
+===================================================================
+--- a/Lib/test/test_ssl.py
++++ b/Lib/test/test_ssl.py
+@@ -147,7 +147,7 @@ def skip_if_broken_ubuntu_ssl(func):
+ needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test")
+
+
+-def test_wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLS, *,
++def test_wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1_2, *,
+ cert_reqs=ssl.CERT_NONE, ca_certs=None,
+ ciphers=None, certfile=None, keyfile=None,
+ **kwargs):
+@@ -883,7 +883,7 @@ class ContextTests(unittest.TestCase):
+ self.assertEqual(ctx.protocol, proto)
+
+ def test_ciphers(self):
+- ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ ctx.set_ciphers("ALL")
+ ctx.set_ciphers("DEFAULT")
+ with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"):
+@@ -1542,7 +1542,7 @@ class SimpleBackgroundTests(unittest.Tes
+
+ def test_connect_with_context(self):
+ # Same as test_connect, but with a separately created context
+- ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
+ s.connect(self.server_addr)
+ self.assertEqual({}, s.getpeercert())
+@@ -1562,7 +1562,7 @@ class SimpleBackgroundTests(unittest.Tes
+ # This should fail because we have no verification certs. Connection
+ # failure crashes ThreadedEchoServer, so run this in an independent
+ # test method.
+- ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ ctx.verify_mode = ssl.CERT_REQUIRED
+ s = ctx.wrap_socket(socket.socket(socket.AF_INET))
+ self.addCleanup(s.close)
+@@ -1595,7 +1595,7 @@ class SimpleBackgroundTests(unittest.Tes
+ with open(SIGNING_CA) as f:
+ pem = f.read()
+ der = ssl.PEM_cert_to_DER_cert(pem)
+- ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ ctx.verify_mode = ssl.CERT_REQUIRED
+ ctx.load_verify_locations(cadata=pem)
+ with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
+@@ -1604,7 +1604,7 @@ class SimpleBackgroundTests(unittest.Tes
+ self.assertTrue(cert)
+
+ # same with DER
+- ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ ctx.verify_mode = ssl.CERT_REQUIRED
+ ctx.load_verify_locations(cadata=der)
+ with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
+@@ -1676,7 +1676,7 @@ class SimpleBackgroundTests(unittest.Tes
+
+ def test_get_ca_certs_capath(self):
+ # capath certs are loaded on request
+- ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ ctx.verify_mode = ssl.CERT_REQUIRED
+ ctx.load_verify_locations(capath=CAPATH)
+ self.assertEqual(ctx.get_ca_certs(), [])
+@@ -1689,8 +1689,8 @@ class SimpleBackgroundTests(unittest.Tes
+ @needs_sni
+ def test_context_setget(self):
+ # Check that the context of a connected socket can be replaced.
+- ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
+- ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
++ ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
++ ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ s = socket.socket(socket.AF_INET)
+ with ctx1.wrap_socket(s) as ss:
+ ss.connect(self.server_addr)
+@@ -1740,7 +1740,7 @@ class SimpleBackgroundTests(unittest.Tes
+ sock.connect(self.server_addr)
+ incoming = ssl.MemoryBIO()
+ outgoing = ssl.MemoryBIO()
+- ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ ctx.verify_mode = ssl.CERT_REQUIRED
+ ctx.load_verify_locations(SIGNING_CA)
+ ctx.check_hostname = True
+@@ -1773,7 +1773,7 @@ class SimpleBackgroundTests(unittest.Tes
+ sock.connect(self.server_addr)
+ incoming = ssl.MemoryBIO()
+ outgoing = ssl.MemoryBIO()
+- ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
+ ctx.verify_mode = ssl.CERT_NONE
+ sslobj = ctx.wrap_bio(incoming, outgoing, False)
+ self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake)