PROTON-2319: [Python] Remove code that only exists to support Python 2.6
- Also modified tox setup to avoid having to modify the file at the cost
  of requiring an environment variable at test time.
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 91f9052..a2d8e74 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -45,7 +45,7 @@
     - name: Install python dependencies
       run: |
         python -m pip install --upgrade pip
-        python -m pip install setuptools wheel tox unittest2
+        python -m pip install setuptools wheel tox
     - name: Install Linux dependencies
       if: runner.os == 'Linux'
       run: |
diff --git a/c/examples/testme b/c/examples/testme
index a405679..c498293 100755
--- a/c/examples/testme
+++ b/c/examples/testme
@@ -21,7 +21,7 @@
 # Run the C examples and verify that they behave as expected.
 # Example executables must be in PATH
 
-from test_unittest import unittest
+import unittest
 
 from test_subprocess import Popen, Server, TestProcessError, check_output
 
diff --git a/c/tests/fdlimit.py b/c/tests/fdlimit.py
index 2fe2e71..0749edf 100644
--- a/c/tests/fdlimit.py
+++ b/c/tests/fdlimit.py
@@ -23,9 +23,9 @@
 import os
 import subprocess
 import time
+import unittest
 
 import test_subprocess
-from test_unittest import unittest
 
 # Check if we can run prlimit to control resources
 try:
diff --git a/cpp/examples/testme b/cpp/examples/testme
index bc6dab8..2078de9 100755
--- a/cpp/examples/testme
+++ b/cpp/examples/testme
@@ -21,18 +21,23 @@
 # Run the C++ examples and verify that they behave as expected.
 # Example executables must be in PATH
 
-import sys, shutil, os, errno
-from test_unittest import  unittest
-from test_subprocess import Popen, TestProcessError, check_output, in_path
-import test_subprocess
+import os, shutil, sys, unittest
+from test_subprocess import Popen, Server as TestServer, check_output, in_path
 from os.path import dirname
 from string import Template
 
-class Server(test_subprocess.Server):
+
+class Server(TestServer):
     @property
     def addr(self):
         return ":%s/example" % self.port
 
+
+class Broker(Server):
+    def __init__(self):
+        super(Broker, self).__init__(["broker", "-a", "//:0"], kill_me=True)
+
+
 def _cyrusSetup(conf_dir):
   """Write out simple SASL config.tests
   """
@@ -53,22 +58,21 @@
     check_output(cmd, shell=True)
     os.environ['PN_SASL_CONFIG_PATH'] = abs_conf_dir
 
+
 # Globally initialize Cyrus SASL configuration
 _cyrusSetup('sasl-conf')
 
-class Broker(Server):
-    def __init__(self):
-        super(Broker, self).__init__(["broker", "-a", "//:0"], kill_me=True)
-
 CLIENT_EXPECT="""Twas brillig, and the slithy toves => TWAS BRILLIG, AND THE SLITHY TOVES
 Did gire and gymble in the wabe. => DID GIRE AND GYMBLE IN THE WABE.
 All mimsy were the borogroves, => ALL MIMSY WERE THE BOROGROVES,
 And the mome raths outgrabe. => AND THE MOME RATHS OUTGRABE.
 """
 
+
 def recv_expect():
     return "".join(['{"sequence"=%s}\n' % (i+1) for i in range(100)])
 
+
 class ContainerExampleTest(unittest.TestCase):
     """Run the container examples, verify they behave as expected."""
 
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index bdd2b4c..f55d807 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -162,11 +162,11 @@
 add_dependencies(py_src_dist generated_c_files)
 
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README.rst.in
-               ${CMAKE_CURRENT_BINARY_DIR}/README.rst
+               ${py_dist_dir}/README.rst
 )
 
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in
-               ${CMAKE_CURRENT_BINARY_DIR}/setup.py
+               ${py_dist_dir}/setup.py
 )
 
 add_custom_command(TARGET py_src_dist
@@ -193,12 +193,6 @@
 add_custom_command(TARGET py_src_dist
                    COMMAND ${CMAKE_COMMAND} -E copy ${PN_C_SOURCE_DIR}/protocol.h "${py_dist_dir}/src")
 
-add_custom_command(TARGET py_src_dist
-                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/README.rst "${py_dist_dir}")
-
-add_custom_command(TARGET py_src_dist
-                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/setup.py "${py_dist_dir}")
-
 foreach(file IN LISTS py_dist_files pysrc)
 add_custom_command(TARGET py_src_dist
                    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${file} "${py_dist_dir}/${file}")
@@ -248,32 +242,18 @@
   COMMAND ${PYTHON_EXECUTABLE} ${python_coverage_options} -- "${py_tests}/proton-test")
 set_tests_properties(python-test PROPERTIES PASS_REGULAR_EXPRESSION "Totals: .* 0 failed")
 
-if(PYTHON_VERSION_MAJOR EQUAL 2 AND PYTHON_VERSION_MINOR LESS 7)
-  execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "import unittest2"
-          RESULT_VARIABLE UNITTEST_MISSING
-          ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
-  if(UNITTEST_MISSING)
-    message(WARNING "unittest2 is not installed. ***some unit tests cannot be run***\ntry 'pip install unittest2' to install unittest2")
-  else(UNITTEST_MISSING)
-    set(PYTHON_TEST_COMMAND "-m" "unittest2")
-  endif(UNITTEST_MISSING)
-else(PYTHON_VERSION_MAJOR EQUAL 2 AND PYTHON_VERSION_MINOR LESS 7)
-  set(PYTHON_TEST_COMMAND "-m" "unittest")
-endif(PYTHON_VERSION_MAJOR EQUAL 2 AND PYTHON_VERSION_MINOR LESS 7)
-
-if (PYTHON_TEST_COMMAND)
-  pn_add_test(
-    INTERPRETED
-    NAME python-integration-test
-    PREPEND_ENVIRONMENT
-      "PATH=${py_path}"
-      "PYTHONPATH=${py_pythonpath}"
-      "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
-    COMMAND
-      ${PYTHON_EXECUTABLE}
-        ${python_coverage_options}
-        ${PYTHON_TEST_COMMAND} discover -v -s "${py_tests}/integration")
-endif(PYTHON_TEST_COMMAND)
+set(PYTHON_TEST_COMMAND "-m" "unittest")
+pn_add_test(
+  INTERPRETED
+  NAME python-integration-test
+  PREPEND_ENVIRONMENT
+    "PATH=${py_path}"
+    "PYTHONPATH=${py_pythonpath}"
+    "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
+  COMMAND
+    ${PYTHON_EXECUTABLE}
+      ${python_coverage_options}
+      ${PYTHON_TEST_COMMAND} discover -v -s "${py_tests}/integration")
 
 check_python_module("tox" TOX_MODULE_FOUND)
 if (NOT TOX_MODULE_FOUND)
@@ -281,7 +261,7 @@
 else ()
   option(ENABLE_TOX_TEST "Enable multi-version python testing with TOX" ON)
 
-  set(tox_default "py26,py27,py35,py36,py37,py38")
+  set(tox_default "py27,py35,py36,py37,py38")
   set(TOX_ENVLIST "" CACHE STRING "List of python environments for TOX tests" )
   mark_as_advanced(TOX_ENVLIST)
 
@@ -292,8 +272,9 @@
     if (CMAKE_BUILD_TYPE MATCHES "Coverage")
       message(STATUS "Building for coverage analysis; skipping the python-tox-tests")
     else ()
-      configure_file(
-        "${CMAKE_CURRENT_SOURCE_DIR}/tox.ini.in"
+      add_custom_command(TARGET py_src_dist
+        COMMAND ${CMAKE_COMMAND} -E copy
+        "${CMAKE_CURRENT_SOURCE_DIR}/tox.ini"
         "${CMAKE_CURRENT_BINARY_DIR}/tox.ini")
       pn_add_test(
         INTERPRETED
@@ -302,6 +283,8 @@
           "PATH=${py_path}"
           "SASLPASSWD=${CyrusSASL_Saslpasswd_EXECUTABLE}"
           "SWIG=${SWIG_EXECUTABLE}"
+          "TOXENV=${TOX_ENVLIST}"
+          "PY_TEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/tests"
         COMMAND ${PYTHON_EXECUTABLE} -m tox)
       set_tests_properties(python-tox-test
         PROPERTIES
diff --git a/python/setup.py.in b/python/setup.py.in
index 9fb607e..d7d616d 100644
--- a/python/setup.py.in
+++ b/python/setup.py.in
@@ -276,7 +276,6 @@
                    "Intended Audience :: Developers",
                    "Programming Language :: Python",
                    "Programming Language :: Python :: 2",
-                   "Programming Language :: Python :: 2.6",
                    "Programming Language :: Python :: 2.7",
                    "Programming Language :: Python :: 3",
                    "Programming Language :: Python :: 3.5",
diff --git a/python/tests/integration/test_PROTON_1709_application_event_object_leak.py b/python/tests/integration/test_PROTON_1709_application_event_object_leak.py
index 6e6d26b..cc6fee9 100644
--- a/python/tests/integration/test_PROTON_1709_application_event_object_leak.py
+++ b/python/tests/integration/test_PROTON_1709_application_event_object_leak.py
@@ -25,16 +25,15 @@
 from __future__ import division
 from __future__ import print_function
 
+import gc
 import platform
 import threading
-import gc
+import unittest
 
 import proton
 from proton.handlers import MessagingHandler
 from proton.reactor import Container, ApplicationEvent, EventInjector
 
-from test_unittest import unittest
-
 
 class Program(MessagingHandler):
     def __init__(self, injector):
diff --git a/python/tests/integration/test_PROTON_1800_syncrequestresponse_fd_leak.py b/python/tests/integration/test_PROTON_1800_syncrequestresponse_fd_leak.py
index 614ed7e..08932bf 100644
--- a/python/tests/integration/test_PROTON_1800_syncrequestresponse_fd_leak.py
+++ b/python/tests/integration/test_PROTON_1800_syncrequestresponse_fd_leak.py
@@ -25,13 +25,15 @@
 from __future__ import print_function
 
 import contextlib
-import socket
-import uuid
 import gc
 import os
-import threading
 import subprocess
+import socket
+import threading
+import unittest
+import uuid
 import warnings
+
 from collections import namedtuple
 
 import cproton
@@ -43,8 +45,6 @@
 from proton.utils import SyncRequestResponse, BlockingConnection
 from proton.handlers import IncomingMessageHandler
 
-from test_unittest import unittest
-
 
 def get_fd_set():
     # type: () -> set[str]
diff --git a/python/tests/integration/test_PROTON_2111_container_ssl_ssldomain_object_leak.py b/python/tests/integration/test_PROTON_2111_container_ssl_ssldomain_object_leak.py
index d0d8533..1563e2d 100644
--- a/python/tests/integration/test_PROTON_2111_container_ssl_ssldomain_object_leak.py
+++ b/python/tests/integration/test_PROTON_2111_container_ssl_ssldomain_object_leak.py
@@ -26,12 +26,12 @@
 from __future__ import print_function
 
 import contextlib
-import platform
-
 import gc
 import os
+import platform
 import socket
 import threading
+import unittest
 
 import cproton
 
@@ -39,8 +39,6 @@
 import proton.utils
 import proton.reactor
 
-from test_unittest import unittest
-
 
 class Broker(proton.handlers.MessagingHandler):
     def __init__(self, acceptor_url, ssl_domain=None):
diff --git a/python/tests/integration/test_PROTON_2116_blocking_connection_object_leak.py b/python/tests/integration/test_PROTON_2116_blocking_connection_object_leak.py
index afe62db..b835b07 100644
--- a/python/tests/integration/test_PROTON_2116_blocking_connection_object_leak.py
+++ b/python/tests/integration/test_PROTON_2116_blocking_connection_object_leak.py
@@ -26,21 +26,21 @@
 from __future__ import division
 from __future__ import print_function
 
-import platform
 import gc
 import logging
 import os
+import platform
 import subprocess
 import sys
 import threading
 import time
+import unittest
 import uuid
 
 import proton.handlers
 import proton.reactor
 import proton.utils
 
-from test_unittest import unittest
 
 logger = logging.getLogger(__name__)
 
diff --git a/python/tests/integration/test_PROTON_2121_blocking_connection_fd_leak.py b/python/tests/integration/test_PROTON_2121_blocking_connection_fd_leak.py
index 58e121c..3160c88 100644
--- a/python/tests/integration/test_PROTON_2121_blocking_connection_fd_leak.py
+++ b/python/tests/integration/test_PROTON_2121_blocking_connection_fd_leak.py
@@ -26,11 +26,12 @@
 from __future__ import print_function
 
 import contextlib
-import socket
 import gc
 import os
+import socket
 import subprocess
 import threading
+import unittest
 import warnings
 
 import cproton
@@ -39,8 +40,6 @@
 import proton.utils
 import proton.reactor
 
-from test_unittest import unittest
-
 
 def get_fd_set():
     # type: () -> set[str]
diff --git a/python/tox.ini b/python/tox.ini
new file mode 100644
index 0000000..e70b23c
--- /dev/null
+++ b/python/tox.ini
@@ -0,0 +1,32 @@
+[tox]
+# This will usually be overridden by ctest setting TOXENV
+envlist = py36,py37,py38
+minversion = 1.7.2
+setupdir = {toxinidir}/dist
+skip_missing_interpreters = True
+
+[testenv]
+usedevelop = False
+setenv =
+    VIRTUAL_ENV={envdir}
+    DEBUG=True
+passenv =
+    PKG_CONFIG_PATH
+    CFLAGS
+    SASLPASSWD
+    TEST_EXE_PREFIX
+    OPENSSL_ia32cap
+commands =
+    python {env:PY_TEST_DIR}/proton-test {posargs:--ignore-file "{env:PY_TEST_DIR}/tox-blacklist"}
+
+[testenv:pep8]
+deps =
+    flake8
+changedir = {[tox]setupdir}
+commands = flake8
+
+[testenv:docs]
+deps =
+    sphinx
+changedir = {[tox]setupdir}
+commands = python setup.py build_sphinx
diff --git a/python/tox.ini.in b/python/tox.ini.in
deleted file mode 100644
index c52f81d..0000000
--- a/python/tox.ini.in
+++ /dev/null
@@ -1,27 +0,0 @@
-[tox]
-envlist = @TOX_ENVLIST@
-minversion = 1.4
-skipdist = True
-setupdir = @py_dist_dir@
-
-[testenv]
-usedevelop = False
-setenv =
-    VIRTUAL_ENV={envdir}
-    DEBUG=True
-passenv =
-    PKG_CONFIG_PATH
-    CFLAGS
-    SASLPASSWD
-    TEST_EXE_PREFIX
-    OPENSSL_ia32cap
-commands =
-    python @CMAKE_SOURCE_DIR@/python/tests/proton-test '{posargs:--ignore-file=@CMAKE_SOURCE_DIR@/python/tests/tox-blacklist}'
-deps =
-    unittest2
-
-[testenv:pep8]
-commands = flake8
-
-[testenv:docs]
-commands = python setup.py build_sphinx
diff --git a/tests/py/test_unittest.py b/tests/py/test_unittest.py
deleted file mode 100644
index 623d63f..0000000
--- a/tests/py/test_unittest.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License
-#
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import sys
-
-__all__ = ['unittest']
-
-
-def _monkey_patch():
-    """Monkey-patch a few unittest 2.7 features for Python 2.6.
-
-    These are not the pretty versions provided by 2.7, but they do the
-    same job as far as correctness is concerned.
-
-    Only used as a measure of last resort if unittest2 is not available.
-    """
-    if not hasattr(unittest.TestCase, "assertMultiLineEqual"):
-        def assertMultiLineEqual(self, a, b, msg=None): self.assertEqual(a, b, msg)
-
-        unittest.TestCase.assertMultiLineEqual = assertMultiLineEqual
-
-    if not hasattr(unittest.TestCase, "assertIn"):
-        def assertIn(self, a, b, msg=None): self.assertTrue(a in b, msg)
-
-        unittest.TestCase.assertIn = assertIn
-
-    if not hasattr(unittest.TestCase, "assertIsNone"):
-        def assertIsNone(self, obj, msg=None): self.assertEqual(obj, None, msg)
-
-        unittest.TestCase.assertIsNone = assertIsNone
-
-    if not hasattr(unittest, "skip"):
-        def skip(reason="Test skipped"):
-            return lambda f: print(reason)
-
-        unittest.skip = skip
-
-    if not hasattr(unittest, "skipIf"):
-        def skipIf(condition, reason):
-            if condition:
-                return skip(reason)
-            return lambda f: f
-
-        unittest.skipIf = skipIf
-
-    if not hasattr(unittest, "skipUnless"):
-        def skipUnless(condition, reason):
-            if not condition:
-                return skip(reason)
-            return lambda f: f
-
-        unittest.skipUnless = skipUnless
-
-
-if sys.version_info >= (2, 7):
-    import unittest
-else:
-    try:
-        import unittest2 as unittest
-    except ImportError:
-        import unittest
-
-        _monkey_patch()