diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 11ab5428615d7af3c4a5b0382024de6520c27f3d..bb471b0b4c0e552eef7a511c4e41ce6d97b35d9e 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -11,6 +11,7 @@ repos:
     hooks:
       - id: trailing-whitespace
         args: [--markdown-linebreak-ext=md]
+        exclude: .patch$
       - id: check-added-large-files
         args: ['--maxkb=4096']
       - id: check-xml
diff --git a/buildconfig/CMake/ExternalSipPyQt4.cmake b/buildconfig/CMake/ExternalSipPyQt4.cmake
deleted file mode 100644
index 3b9771942d80b98f0947d9944fd6735654cc7dc8..0000000000000000000000000000000000000000
--- a/buildconfig/CMake/ExternalSipPyQt4.cmake
+++ /dev/null
@@ -1,82 +0,0 @@
-include(ExternalProject)
-include(ProcessorCount)
-
-set(_SIP_PYQT_DIR extern-pyt4-sip)
-set(_SIP_PYQT_INSTALL_DIR ${_SIP_PYQT_DIR}/install)
-
-# sipdir - use different variables to standard sip installation to be able to distingish it
-set(PYQT4_SIP_INCLUDE_DIR "${CMAKE_BINARY_DIR}/${_SIP_PYQT_INSTALL_DIR}/include"  CACHE STRING "sip include directory" FORCE)
-set(PYQT4_SIP_EXECUTABLE "${CMAKE_BINARY_DIR}/${_SIP_PYQT_INSTALL_DIR}/bin/sip" CACHE STRING "sip executable" FORCE)
-set(PYQT4_SIP_VERSION "041307" CACHE STRING "sip hexadecimal string" FORCE)
-set(PYQT4_SIP_VERSION_STR "4.19.7" CACHE STRING "sip version string" FORCE)
-ExternalProject_Add(extern-pyqt4-sip
-  PREFIX ${_SIP_PYQT_DIR}/sip
-  INSTALL_DIR ${_SIP_PYQT_INSTALL_DIR}
-  URL https://sourceforge.net/projects/pyqt/files/sip/sip-4.19.7/sip-4.19.7.tar.gz/download
-  URL_HASH MD5=ae4f2db79713046d61b2a44e5ee1e3ab
-  CONFIGURE_COMMAND "${Python_EXECUTABLE}" "<SOURCE_DIR>/configure.py"
-    --sip-module=PyQt4.sip
-    --bindir=<INSTALL_DIR>/bin
-    --destdir=<INSTALL_DIR>/lib/site-packages
-    --incdir=<INSTALL_DIR>/include
-    --sipdir=<INSTALL_DIR>/share/sip
-  BUILD_COMMAND make 2> build.log
-)
-
-# PyQt4
-set(PYQT4_VERSION "040c01" CACHE STRING "PyQt4's version as a 6-digit hexadecimal number" FORCE)
-set(PYQT4_VERSION_STR "4.12.1" CACHE STRING "PyQt4's version as a human-readable string" FORCE)
-set(PYQT4_VERSION_TAG "Qt_4_8_6" CACHE STRING "The Qt version tag used by PyQt4's .sip files" FORCE)
-set(PYQT4_SIP_DIR "${CMAKE_BINARY_DIR}/${_SIP_PYQT_INSTALL_DIR}/share/sip" CACHE PATH "The base directory where PyQt4's .sip files are installed" FORCE)
-set(PYQT4_SIP_FLAGS "-x VendorID -t WS_X11 -x PyQt_NoPrintRangeBug -t Qt_4_8_6" CACHE STRING "The SIP flags used to build PyQt4" FORCE)
-set(PRIVATE_PYQT_SITE_PACKAGES ${CMAKE_BINARY_DIR}/${_SIP_PYQT_INSTALL_DIR}/lib/site-packages)
-set(_pyqt4_lib_site_packages ${PRIVATE_PYQT_SITE_PACKAGES}/PyQt4)
-
-# Write a wrapper pyuic script so it can find out internal copy of PyQt4
-set(PYQT4_PYUIC "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/internal-pyuic.py" CACHE STRING "Location of the pyuic script" FORCE)
-configure_file(${CMAKE_MODULE_PATH}/internal-pyuic.py.in ${PYQT4_PYUIC} @ONLY)
-
-# Determine core count for make step
-ProcessorCount(NPROCESSORS)
-if(NPROCESSORS EQUAL 0)
-  set(NPROCESSORS 1)
-endif()
-
-ExternalProject_Add(extern-pyqt4
-  PREFIX ${_SIP_PYQT_DIR}/pyqt4
-  INSTALL_DIR ${_SIP_PYQT_INSTALL_DIR}
-  URL https://sourceforge.net/projects/pyqt/files/PyQt4/PyQt-4.12.1/PyQt4_gpl_x11-4.12.1.tar.gz/download
-  URL_HASH MD5=0112e15858cd7d318a09e7366922f874
-  PATCH_COMMAND patch -p1 --input ${CMAKE_SOURCE_DIR}/buildconfig/CMake/pyqt4_qreal_float_support.patch
-    COMMAND patch -p0 --input ${CMAKE_SOURCE_DIR}/buildconfig/CMake/pyqt4_disable_unnecessary_modules.patch
-    # patch configure to pick up sipconfig built above
-    COMMAND sed -i -e "/^import sipconfig/i sys.path.insert(0, \"${_pyqt4_lib_site_packages}\")" "<SOURCE_DIR>/configure.py"
-  CONFIGURE_COMMAND "${Python_EXECUTABLE}" "<SOURCE_DIR>/configure.py"
-    --assume-shared
-    --confirm-license
-    --bindir=<INSTALL_DIR>/bin
-    --destdir=<INSTALL_DIR>/lib/site-packages
-    --sipdir=<INSTALL_DIR>/share/sip
-    --no-designer-plugin
-    --no-timestamp
-    --no-deprecated
-    --qmake=/usr/bin/qmake-qt4
-    --no-qsci-api
-  BUILD_COMMAND make -j${NPROCESSORS} 2> build.log
-  DEPENDS extern-pyqt4-sip
-)
-
-# Write out .pth file to find this. We ensure to insert our path ahead of others so it takes precendence over the system
-# We assume we only have to support a single-configuration build type on Linux
-file(WRITE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/private-pyqt4.pth
-"import sys; sys.__plen = len(sys.path)
-${PRIVATE_PYQT_SITE_PACKAGES}
-${_pyqt4_lib_site_packages}
-import sys; new = sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p = getattr(sys, '__egginsert', 0); sys.path[p:p] = new; sys.__egginsert = p + len(new)
-")
-
-# Package PyQt. We assume this is for Python 3
-install(DIRECTORY ${PRIVATE_PYQT_SITE_PACKAGES}/PyQt4
-        DESTINATION ${LIB_DIR}
-        PATTERN "__pycache__" EXCLUDE
-        PATTERN "port_v2" EXCLUDE)
diff --git a/buildconfig/CMake/pyqt4_disable_unnecessary_modules.patch b/buildconfig/CMake/pyqt4_disable_unnecessary_modules.patch
deleted file mode 100644
index 0d44a7f01d1fefb491cd5cec9fbf0ac259eabfda..0000000000000000000000000000000000000000
--- a/buildconfig/CMake/pyqt4_disable_unnecessary_modules.patch
+++ /dev/null
@@ -1,94 +0,0 @@
---- configure.py.orig	2020-01-09 15:07:19.231636923 +0000
-+++ configure.py	2020-01-09 15:10:28.159688544 +0000
-@@ -1,19 +1,19 @@
- # This script generates the PyQt configuration and generates the Makefiles.
- #
- # Copyright (c) 2016 Riverbank Computing Limited <info@riverbankcomputing.com>
--#
-+#
- # This file is part of PyQt4.
--#
-+#
- # This file may be used under the terms of the GNU General Public License
- # version 3.0 as published by the Free Software Foundation and appearing in
- # the file LICENSE included in the packaging of this file.  Please review the
- # following information to ensure the GNU General Public License version 3.0
- # requirements will be met: http://www.gnu.org/copyleft/gpl.html.
--#
-+#
- # If you do not wish to use this file under the terms of the GPL version 3.0
- # then you may purchase a commercial license.  For more information contact
- # info@riverbankcomputing.com.
--#
-+#
- # This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- # WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
-@@ -90,7 +90,7 @@ def find_default_qmake():
-
-     for d in path.split(os.pathsep):
-         qmake = os.path.join(d, base_qmake)
--
-+
-         if os.access(qmake, os.X_OK):
-             return qmake
-
-@@ -109,7 +109,7 @@ def create_optparser():
-         if not os.path.isdir(value):
-             raise optparse.OptionValueError("'%s' is not a directory" % value)
-         setattr(parser.values, option.dest, os.path.abspath(value))
--
-+
-     def store_abspath_file(option, opt_str, value, parser):
-         if not os.path.isfile(value):
-             raise optparse.OptionValueError("'%s' is not a file" % value)
-@@ -342,8 +342,8 @@ class ConfigurePyQt4:
-
-         check_module("QtGui", "qwidget.h", "new QWidget()")
-         check_module("QtHelp", "qhelpengine.h", "new QHelpEngine(\"foo\")")
--        check_module("QtMultimedia", "QAudioDeviceInfo",
--                "new QAudioDeviceInfo()")
-+        # check_module("QtMultimedia", "QAudioDeviceInfo",
-+        #         "new QAudioDeviceInfo()")
-         check_module("QtNetwork", "qhostaddress.h", "new QHostAddress()")
-
-         # Qt v4.7 was current when we added support for QtDBus and we didn't
-@@ -364,14 +364,14 @@ class ConfigurePyQt4:
-                 extra_libs=sql_libs)
-         check_module("QtSvg", "qsvgwidget.h", "new QSvgWidget()")
-         check_module("QtTest", "QtTest", "QTest::qSleep(0)")
--        check_module("QtWebKit", "qwebpage.h", "new QWebPage()")
-+        # check_module("QtWebKit", "qwebpage.h", "new QWebPage()")
-         check_module("QtXml", "qdom.h", "new QDomDocument()")
-         check_module("QtXmlPatterns", "qxmlname.h", "new QXmlName()")
-         check_module("phonon", "phonon/videowidget.h",
-                 "new Phonon::VideoWidget()")
--        check_module("QtAssistant", "qassistantclient.h",
--                "new QAssistantClient(\"foo\")", extra_lib_dirs=ass_lib_dirs,
--                extra_libs=ass_libs)
-+        # check_module("QtAssistant", "qassistantclient.h",
-+        #         "new QAssistantClient(\"foo\")", extra_lib_dirs=ass_lib_dirs,
-+        #         extra_libs=ass_libs)
-
-         if qt_shared == '':
-             sipconfig.inform("QtDesigner module disabled with static Qt libraries.")
-@@ -503,8 +503,8 @@ class ConfigurePyQt4:
-         if "QtTest" in pyqt_modules:
-             generate_code("QtTest")
-
--        if "QtWebKit" in pyqt_modules:
--            generate_code("QtWebKit")
-+        # if "QtWebKit" in pyqt_modules:
-+        #     generate_code("QtWebKit")
-
-         if "QtXml" in pyqt_modules:
-             generate_code("QtXml")
-@@ -1511,7 +1511,7 @@ def needed_qt_libs(mname, qt_libs):
-         "QtSql": ["QtGui"],
-         "QtSvg": ["QtGui"],
-         "QtTest": ["QtGui"],
--        "QtWebKit": ["QtNetwork", "QtGui"],
-+        # "QtWebKit": ["QtNetwork", "QtGui"],
-         "QtXml": ["QtCore"],
-         "QtXmlPatterns": ["QtNetwork", "QtCore"],
-         "phonon": ["QtGui"],
diff --git a/buildconfig/CMake/pyqt4_qreal_float_support.patch b/buildconfig/CMake/pyqt4_qreal_float_support.patch
deleted file mode 100644
index d8c3ef74723e77f9ee28ca8303ebf7d669dc6708..0000000000000000000000000000000000000000
--- a/buildconfig/CMake/pyqt4_qreal_float_support.patch
+++ /dev/null
@@ -1,240 +0,0 @@
-From: Michael Casadevall <mcasadevall@debian.org>
-Date: Thu, 8 Oct 2015 12:56:35 -0700
-Subject: Add QList<double> support explicitly when qreal is not double
-
----
- sip/QtCore/qlist.sip | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 224 insertions(+)
-
-diff --git a/sip/QtCore/qlist.sip b/sip/QtCore/qlist.sip
-index 978e576..63002d2 100644
---- a/sip/QtCore/qlist.sip
-+++ b/sip/QtCore/qlist.sip
-@@ -814,3 +814,227 @@ template<qreal, TYPE>
-     return sipGetState(sipTransferObj);
- %End
- };
-+
-+// If we're on an architecture where qreal != double, then we need to also
-+// explicately handle doubles. On architectures where qreal == double, they
-+// will automaticially be cast upwards
-+
-+%If (!PyQt_qreal_double)
-+
-+%If (Qt_4_3_0 -)
-+// QList<QPair<double, double> > is implemented as a Python list of 2-element tuples.
-+%MappedType QList<QPair<double, double> >
-+{
-+%TypeHeaderCode
-+#include <qlist.h>
-+#include <qpair.h>
-+%End
-+
-+%ConvertFromTypeCode
-+    // Create the list.
-+    PyObject *l;
-+
-+    if ((l = PyList_New(sipCpp->size())) == NULL)
-+        return NULL;
-+
-+    // Set the list elements.
-+    for (int i = 0; i < sipCpp->size(); ++i)
-+    {
-+        const QPair<double, double> &p = sipCpp->at(i);
-+        PyObject *pobj;
-+
-+        if ((pobj = Py_BuildValue((char *)"dd", p.first, p.second)) == NULL)
-+        {
-+            Py_DECREF(l);
-+
-+            return NULL;
-+        }
-+
-+        PyList_SET_ITEM(l, i, pobj);
-+    }
-+
-+    return l;
-+%End
-+
-+%ConvertToTypeCode
-+    SIP_SSIZE_T len;
-+
-+    // Check the type if that is all that is required.
-+    if (sipIsErr == NULL)
-+    {
-+        if (!PySequence_Check(sipPy) || (len = PySequence_Size(sipPy)) < 0)
-+            return 0;
-+
-+        for (SIP_SSIZE_T i = 0; i < len; ++i)
-+        {
-+            PyObject *tup = PySequence_ITEM(sipPy, i);
-+
-+            if (!PySequence_Check(tup) || PySequence_Size(tup) != 2)
-+                return 0;
-+        }
-+
-+        return 1;
-+    }
-+
-+    QList<QPair<double, double> > *ql = new QList<QPair<double, double> >;
-+    len = PySequence_Size(sipPy);
-+
-+    for (SIP_SSIZE_T i = 0; i < len; ++i)
-+    {
-+        PyObject *tup = PySequence_ITEM(sipPy, i);
-+
-+        double first = PyFloat_AsDouble(PySequence_ITEM(tup, 0));
-+        double second = PyFloat_AsDouble(PySequence_ITEM(tup, 1));
-+
-+        ql->append(QPair<double, double>(first, second));
-+    }
-+
-+    *sipCppPtr = ql;
-+
-+    return sipGetState(sipTransferObj);
-+%End
-+};
-+%End
-+%If (Qt_4_3_0 -)
-+// QList<QPair<double, TYPE> > is implemented as a Python list of 2-element tuples.
-+template<double, TYPE>
-+%MappedType QList<QPair<double, TYPE> >
-+{
-+%TypeHeaderCode
-+#include <qlist.h>
-+#include <qpair.h>
-+%End
-+
-+%ConvertFromTypeCode
-+    // Create the list.
-+    PyObject *l;
-+
-+    if ((l = PyList_New(sipCpp->size())) == NULL)
-+        return NULL;
-+
-+    // Set the list elements.
-+    for (int i = 0; i < sipCpp->size(); ++i)
-+    {
-+        const QPair<double, TYPE> &p = sipCpp->at(i);
-+        TYPE *t = new TYPE(p.second);
-+        PyObject *pobj;
-+
-+        if ((pobj = sipBuildResult(NULL, "(dB)", p.first, t, sipClass_TYPE, sipTransferObj)) == NULL)
-+        {
-+            Py_DECREF(l);
-+            delete t;
-+
-+            return NULL;
-+        }
-+
-+        PyList_SET_ITEM(l, i, pobj);
-+    }
-+
-+    return l;
-+%End
-+
-+%ConvertToTypeCode
-+    SIP_SSIZE_T len;
-+
-+    // Check the type if that is all that is required.
-+    if (sipIsErr == NULL)
-+    {
-+        if (!PySequence_Check(sipPy) || (len = PySequence_Size(sipPy)) < 0)
-+            return 0;
-+
-+        for (SIP_SSIZE_T i = 0; i < len; ++i)
-+        {
-+            PyObject *tup = PySequence_ITEM(sipPy, i);
-+
-+            if (!PySequence_Check(tup) || PySequence_Size(tup) != 2)
-+                return 0;
-+
-+            if (!sipCanConvertToInstance(PySequence_ITEM(tup, 1), sipClass_TYPE, SIP_NOT_NONE))
-+                return 0;
-+        }
-+
-+        return 1;
-+    }
-+
-+    QList<QPair<double, TYPE> > *ql = new QList<QPair<double, TYPE> >;
-+    len = PySequence_Size(sipPy);
-+
-+    for (SIP_SSIZE_T i = 0; i < len; ++i)
-+    {
-+        PyObject *tup = PySequence_ITEM(sipPy, i);
-+        double d;
-+        int state;
-+
-+        d = PyFloat_AsDouble(PySequence_ITEM(tup, 0));
-+        TYPE *t = reinterpret_cast<TYPE *>(sipConvertToInstance(PySequence_ITEM(tup, 1), sipClass_TYPE, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr));
-+
-+        if (*sipIsErr)
-+        {
-+            sipReleaseInstance(t, sipClass_TYPE, state);
-+
-+            delete ql;
-+            return 0;
-+        }
-+
-+        ql->append(QPair<double, TYPE>(d, *t));
-+
-+        sipReleaseInstance(t, sipClass_TYPE, state);
-+    }
-+
-+    *sipCppPtr = ql;
-+
-+    return sipGetState(sipTransferObj);
-+%End
-+};
-+%End
-+
-+// QList<double> is implemented as a Python list of doubles.
-+%MappedType QList<double>
-+{
-+%TypeHeaderCode
-+#include <qlist.h>
-+%End
-+
-+%ConvertFromTypeCode
-+    // Create the list.
-+    PyObject *l;
-+
-+    if ((l = PyList_New(sipCpp->size())) == NULL)
-+        return NULL;
-+
-+    // Set the list elements.
-+    for (int i = 0; i < sipCpp->size(); ++i)
-+    {
-+        PyObject *pobj;
-+
-+        if ((pobj = PyFloat_FromDouble(sipCpp->value(i))) == NULL)
-+        {
-+            Py_DECREF(l);
-+
-+            return NULL;
-+        }
-+
-+        PyList_SET_ITEM(l, i, pobj);
-+    }
-+
-+    return l;
-+%End
-+
-+%ConvertToTypeCode
-+    // Check the type if that is all that is required.
-+    if (sipIsErr == NULL)
-+        return (PySequence_Check(sipPy) && PySequence_Size(sipPy) >= 0);
-+
-+    QList<double> *ql = new QList<double>;
-+    SIP_SSIZE_T len = PySequence_Size(sipPy);
-+
-+    for (SIP_SSIZE_T i = 0; i < len; ++i)
-+        ql->append(PyFloat_AsDouble(PySequence_ITEM(sipPy, i)));
-+
-+    *sipCppPtr = ql;
-+
-+    return sipGetState(sipTransferObj);
-+%End
-+};
-+
-+%End
diff --git a/buildconfig/CMake/span_disable_testing.patch b/buildconfig/CMake/span_disable_testing.patch
index 739d81b6b54c0739c0c19196c17b35c8dd34b4e0..6d2b0b1a01e9618b12c357a088acd68afe0dc3f5 100644
--- a/buildconfig/CMake/span_disable_testing.patch
+++ b/buildconfig/CMake/span_disable_testing.patch
@@ -5,15 +5,15 @@ index 7ad07e2..0470696 100644
 @@ -2,7 +2,7 @@
  cmake_minimum_required(VERSION 3.8)
  project(span LANGUAGES CXX)
-
+ 
 -enable_testing()
 +# enable_testing()
-
+ 
  add_library(span INTERFACE)
  target_sources(span INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include/tcb/span.hpp)
 @@ -11,4 +11,4 @@ target_compile_features(span INTERFACE cxx_std_11)
-
+ 
  set(TCB_SPAN_TEST_CXX_STD 11 CACHE STRING "C++ standard version for testing")
-
+ 
 -add_subdirectory(test)
 +# add_subdirectory(test)
diff --git a/buildconfig/pyport.patch b/buildconfig/pyport.patch
deleted file mode 100644
index 03fefffe34cbeac5422dcca1dd63eff2653f8ae6..0000000000000000000000000000000000000000
--- a/buildconfig/pyport.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/pyport.h b/pyport.h
---- a/pyport.h
-+++ b/pyport.h
-@@ -657,6 +657,9 @@
- #endif
-
- #ifdef _PY_PORT_CTYPE_UTF8_ISSUE
-+
-+#ifndef __cplusplus
-+
- #include <ctype.h>
- #include <wctype.h>
- #undef isalnum
-@@ -673,7 +676,11 @@
- #define tolower(c) towlower(btowc(c))
- #undef toupper
- #define toupper(c) towupper(btowc(c))
--#endif
-+
-+#endif /* !__cplusplus */
-+
-+
-+#endif /* _PY_PORT_CTYPE_UTF8_ISSUE */
-
-
- /* Declarations for symbol visibility.
diff --git a/buildconfig/qglobal.patch b/buildconfig/qglobal.patch
deleted file mode 100644
index d3922418e721b37f90ebb84f1d455106b1e5181e..0000000000000000000000000000000000000000
--- a/buildconfig/qglobal.patch
+++ /dev/null
@@ -1,7 +0,0 @@
-319c319,322
-< #  if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6)
----
-> #  if !defined(MAC_OS_X_VERSION_10_7)
-> #       define MAC_OS_X_VERSION_10_7 MAC_OS_X_VERSION_10_6 + 1
-> #  endif
-> #  if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_7)