diff --git a/.github/workflows/ciwheel.yml b/.github/workflows/ciwheel.yml
index fc20275873d47fc563897cb4f5ecac5d5ddaf92e..77f094fbcbf7add4b20a973498353388dcaf53ae 100644
--- a/.github/workflows/ciwheel.yml
+++ b/.github/workflows/ciwheel.yml
@@ -24,10 +24,38 @@ jobs:
         with:
           fetch-depth: 0
           submodules: recursive
-      - name: Install cibuildwheel
-        run: python3 -m pip install cibuildwheel
-      - name: Build wheels
-        run: python3 -m cibuildwheel --output-dir dist
+      - name: Update pip
+        run: python -m pip install --upgrade pip
+
+      - name: Build wheels Linux
+        if: ${{ startsWith(matrix.os, 'ubuntu') }}
+        uses: pypa/cibuildwheel@v2.3.0
+        with:
+          output-dir: dist
+        env:
+          CIBW_BEFORE_ALL: yum -y install libxml2-devel
+          CIBW_BEFORE_BUILD: python -m pip install numpy setuptools scikit-build ninja cmake
+          CIBW_BUILD: "cp3*-manylinux_x86_64"
+          CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
+          CIBW_ARCHS_LINUX: x86_64
+          CIBW_REPAIR_WHEEL_COMMAND: 'auditwheel repair -w {dest_dir} {wheel} && python /project/scripts/patchwheel.py {dest_dir}'
+          CIBW_TEST_COMMAND: python -m unittest discover -v -s {project}/python
+
+      - name: Build wheels macos
+        if: ${{ startsWith(matrix.os, 'macos') }}
+        uses: pypa/cibuildwheel@v2.3.0
+        with:
+          output-dir: dist
+        env:
+          MACOSX_DEPLOYMENT_TARGET: "10.15" #needed to undo some CIBW settings
+          CIBW_BEFORE_BUILD: python -m pip install numpy setuptools scikit-build ninja cmake
+          CIBW_BUILD: "cp3*-macosx_x86_64"
+          CIBW_ARCHS_MACOS: x86_64 universal2
+          CIBW_TEST_COMMAND: python -m unittest discover -v -s {project}/python
+
+      # this action runs auditwheel automatically with the following args:
+      # https://cibuildwheel.readthedocs.io/en/stable/options/#repair-wheel-command
+
       - uses: actions/upload-artifact@v2
         with:
           name: dist
@@ -40,16 +68,18 @@ jobs:
     steps:
       - name: Set up Python
         uses: actions/setup-python@v2
+      - name: Update pip
+        run: python -m pip install --upgrade pip
       - name: Get packages
-        run: python3 -m pip install build
+        run: python -m pip install numpy setuptools scikit-build ninja cmake
       - uses: actions/checkout@v2
         with:
           fetch-depth: 0
           submodules: recursive
       - name: Make sdist
-        run: python3 -m build -s
+        run:  python setup.py sdist
       - name: Install sdist
-        run:  python3 -m pip install dist/arbor*.tar.gz
+        run:  python -m pip install dist/arbor*.tar.gz
       - name: Run Python tests
         run: python3 -m unittest discover -v -s python
       - name: Run Python examples
diff --git a/.github/workflows/test-everything.yml b/.github/workflows/test-everything.yml
index 21c7d6063595642257c237ba0793ab839cabb300..d540ee525605118675c9cfaf15519f28e95a8a6f 100644
--- a/.github/workflows/test-everything.yml
+++ b/.github/workflows/test-everything.yml
@@ -18,7 +18,7 @@ jobs:
             os:    "ubuntu-18.04",
             cc:    "gcc-8",
             cxx:   "g++-8",
-            py:    "3.7",
+            py:    "3.6",
             cmake: "3.18.x",
             mpi:   "ON",
             simd:  "OFF"
@@ -28,7 +28,7 @@ jobs:
             os:    "ubuntu-18.04",
             cc:    "clang-8",
             cxx:   "clang++-8",
-            py:    "3.7",
+            py:    "3.6",
             cmake: "3.18.x",
             mpi:   "ON",
             simd:  "OFF"
@@ -38,7 +38,7 @@ jobs:
             os:    "macos-10.15",
             cc:    "clang",
             cxx:   "clang++",
-            py:    "3.7",
+            py:    "3.6",
             cmake: "3.18.x",
             mpi:   "ON",
             simd:  "OFF"
@@ -48,7 +48,7 @@ jobs:
             os:    "ubuntu-20.04",
             cc:    "gcc-10",
             cxx:   "g++-10",
-            py:    "3.10",
+            py:    "3.9",
             cmake: "3.22.x",
             mpi:   "ON",
             simd:  "OFF"
@@ -58,7 +58,7 @@ jobs:
             os:    "ubuntu-20.04",
             cc:    "gcc-10",
             cxx:   "g++-10",
-            py:    "3.10",
+            py:    "3.9",
             cmake: "3.22.x",
             mpi:   "OFF",
             simd:  "ON"
@@ -68,7 +68,7 @@ jobs:
             os:    "ubuntu-20.04",
             cc:    "clang-10",
             cxx:   "clang++-10",
-            py:    "3.10",
+            py:    "3.9",
             cmake: "3.22.x",
             mpi:   "ON",
             simd:  "OFF"
@@ -78,7 +78,7 @@ jobs:
             os:    "macos-11",
             cc:    "clang",
             cxx:   "clang++",
-            py:    "3.10",
+            py:    "3.9",
             cmake: "3.22.x",
             mpi:   "ON",
             simd:  "OFF"
@@ -202,12 +202,16 @@ jobs:
     name: "Pip build test + Python examples test"
     runs-on: ubuntu-latest
     steps:
+      - name: Update pip
+        run: python -m pip install --upgrade pip
+      - name: Install Python packages
+        run:  pip install numpy setuptools scikit-build ninja cmake
       - name: Clone w/ submodules
         uses: actions/checkout@v2
         with:
           submodules: recursive
       - name: Build and install Arbor using pip + build flags
-        run: CMAKE_ARGS="-DARB_VECTORIZE=ON -DARB_ARCH=native" python3 -m pip install .
+        run: python3 -m pip install --verbose --install-option="-DARB_VECTORIZE=ON" --install-option="-DARB_ARCH=native" .
       - name: Check that build flags match
         run: |
           python3 -c "import arbor; print(arbor.config())" | grep -q "'arch': 'native'"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 69c18331746ed3afa08df83e028c1d42d38a5c92..48acc89b8d20808bb25ae986d0df45edb74731c6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -302,7 +302,7 @@ endif()
 #----------------------------------------------------------
 
 # The minimum version of Python supported by Arbor.
-set(arb_py_version 3.7.0)
+set(arb_py_version 3.6.0)
 
 if(DEFINED PYTHON_EXECUTABLE)
     set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE})
@@ -311,7 +311,7 @@ endif()
 if(ARB_WITH_PYTHON)
     cmake_dependent_option(ARB_USE_BUNDLED_PYBIND11 "Use bundled pybind11" ON "ARB_WITH_PYTHON;ARB_USE_BUNDLED_LIBS" OFF)
 
-    if(DEFINED ENV{CIBUILDWHEEL} AND (UNIX AND NOT APPLE))
+    if(DEFINED ENV{CIBUILDWHEEL})
         find_package(Python3 ${arb_py_version} COMPONENTS Interpreter Development.Module REQUIRED)
     else()
         find_package(Python3 ${arb_py_version} COMPONENTS Interpreter Development REQUIRED)
diff --git a/doc/dependencies.csv b/doc/dependencies.csv
index f11919b43e305e9e530c15f88f7672ca862b8deb..8cbc63c4bc747b683c8c864c5d68ba121e9732e9 100644
--- a/doc/dependencies.csv
+++ b/doc/dependencies.csv
@@ -19,7 +19,7 @@ bench,Google-benchmark,,submodule ``ext/google-benchmark``,
 --,fmt,,submodule ``ext/fmt``,
 --,tinyopt,,source copy ``ext/tinyopt``,
 ARB_WITH_PYTHON,pybind11,,submodule ``python/pybind11``,
-ARB_WITH_PYTHON,Python,3.7,Python compatiblity is the range between the latest officially released point version and the minimum here specified.,"* it is not more advanced than the version specified by NEP 29.
+ARB_WITH_PYTHON,Python,3.6,Python compatiblity is the range between the latest officially released point version and the minimum here specified.,"* it is not more advanced than the version specified by NEP 29.
 * it is available as a cray-python version on Piz Daint
 * it is available on labs.ebrains.eu
 
diff --git a/doc/install/build_install.rst b/doc/install/build_install.rst
index de3d12dee9ccbe43c37dfd748b8bc33fbc8404f9..de6f6edec7b98eb55fbe99d92392478543431fb0 100644
--- a/doc/install/build_install.rst
+++ b/doc/install/build_install.rst
@@ -135,7 +135,7 @@ More information on building with MPI is in the `HPC cluster section <cluster_>`
 Python
 ~~~~~~
 
-Arbor has a Python frontend, for which a minimum of Python 3.7 is required.
+Arbor has a Python frontend, for which a minimum of Python 3.6 is required.
 In addition, `numpy` is a runtime requirement for the Python package.
 In order to use MPI in combination with the python frontend the
 `mpi4py <https://mpi4py.readthedocs.io/en/stable/install.html#>`_
diff --git a/doc/install/python.rst b/doc/install/python.rst
index 78fbf6cc7cbe6720a1a16c7e73d436ae3df7d15f..c4f7ab46893a3a349f6f80f144243ad015687c0c 100644
--- a/doc/install/python.rst
+++ b/doc/install/python.rst
@@ -6,7 +6,7 @@ Python Installation
 Arbor's Python API will be the most convenient interface for most users.
 
 .. note::
-    Arbor requires Python version 3.7 and later. It is advised that you update ``pip`` as well.
+    Arbor requires Python version 3.6 and later. It is advised that you update ``pip`` as well.
     We strongly encourage using ``pip`` to install Arbor.
     
     To get help in case of problems installing with pip, run pip with the ``--verbose`` flag, and attach the output
@@ -42,11 +42,15 @@ You are now ready to use Arbor! You can continue reading these documentation pag
     for any other platforms than listed above, ``pip`` will attempt a build from source and thus require these
     packages as well.
 
-    * Ubuntu/Debian: ``git cmake gcc python3-dev python3-pip libxml2-dev``
-    * Fedora/CentOS/OpenSuse: ``git cmake gcc-c++ python3-devel python3-pip libxml2-devel``
-    * MacOS: get ``brew`` `here <https://brew.sh>`_ and run ``brew install cmake clang python3 libxml2``
+    * Ubuntu/Debian: `git cmake gcc python3-dev python3-pip libxml2-dev`
+    * Fedora/CentOS/OpenSuse: `git cmake gcc-c++ python3-devel python3-pip libxml2-devel`
+    * MacOS: get `brew` `here <https://brew.sh>`_ and run `brew install cmake clang python3 libxml2`
     * Windows: the simplest way is to use `WSL <https://docs.microsoft.com/en-us/windows/wsl/install-win10>`_ and then follow the instructions for Ubuntu.
 
+    In addition, you'll need a few Python packages present:
+
+    ``pip3 install ninja scikit-build wheel setuptools numpy``
+
 .. _in_python_custom:
 
 Customising Arbor
@@ -75,11 +79,12 @@ Every time you make changes to the code, you'll have to repeat the second step.
 Advanced options
 ^^^^^^^^^^^^^^^^
 
-Arbor comes with a few compilation options, some of them related to advanced forms of parallelism and other features.
-The options and flags are the same :ref:`as documented for the CMAKE build <quickstart>`, but they are passed differently.
-To enable more, they must be placed in the ``CMAKE_ARGS`` environment variable.
-The simplest way to do this is by prepending the ``pip`` command with ``CMAKE_ARGS=""``,
-where you place the arguments separated by space inside the quotes.
+By default Arbor is installed with multi-threading enabled. To enable more
+advanced forms of parallelism and other features, Arbor comes with a few
+compilation options. These are of the form ``-D<KEY>=<VALUE>``, must be appended
+to the ``pip`` invocation via ``--install-option="-D<...>" --install-option="-D<...>" ...`` and can
+be used on both local (``pip3 install ./arbor``) and remote (``pip3 install
+arbor``) copies of Arbor. See the examples below.
 
 .. Note::
 
@@ -87,6 +92,9 @@ where you place the arguments separated by space inside the quotes.
    to remove the ``_skbuild`` directory. If you had Arbor installed already,
    you may need to remove it first before you can (re)compile it with the flags you need.
 
+   Also, make sure to pass each option individually via
+   ``--install-option="..."``.
+
 The following flags can be used to configure the installation:
 
 * ``ARB_WITH_NEUROML=<ON|OFF>``: Enable support for NeuroML2 morphologies,
@@ -111,14 +119,6 @@ The following flags can be used to configure the installation:
    and ``CMake`` under the hood, so all flags and options valid in ``CMake`` can
    be used in this fashion.
 
-   Allthough the
-   `scikit-build documentation <https://scikit-build.readthedocs.io/en/latest/usage.html#environment-variable-configuration>`_
-   mentions that you can also pass the build options with ``--install-option=""``,
-   this will cause ``pip`` to build all dependencies, including all build-dependencies,
-   instead of downloading them from PyPI.
-   ``CMAKE_ARGS=""`` saves you the build time, and also downloading and setting up the dependencies they in turn require to be present.
-   Setting ``CMAKE_ARGS=""`` is in addition compatible with build front-ends like `build <https://pypa-build.readthedocs.io>`_.
-
    Detailed instructions on how to install using CMake are in the :ref:`Python
    configuration <install-python>` section of the :ref:`installation guide
    <in_build_install>`. CMake is recommended if you need more control over
@@ -138,33 +138,33 @@ In the examples below we assume you are installing from a local copy.
 
 .. code-block:: bash
 
-    CMAKE_ARGS="-DARB_WITH_MPI=ON" pip3 install ./arbor
+    pip3 install ./arbor --install-option="-DARB_WITH_MPI=ON"
 
 **Compile with** :ref:`vectorization <install-vectorize>` on a system with a SkyLake
 :ref:`architecture <install-architecture>`:
 
 .. code-block:: bash
 
-    CMAKE_ARGS="-DARB_VECTORIZE=ON -DARB_ARCH=skylake" pip3 install ./arbor
-    
+    pip3 install ./arbor --install-option="-DARB_VECTORIZE=ON" --install-option="-DARB_ARCH=skylake"
+
 **Enable NVIDIA GPUs (compiled with nvcc)**. This requires the :ref:`CUDA toolkit <install-gpu>`:
 
 .. code-block:: bash
 
-    CMAKE_ARGS="-DARB_GPU=cuda" pip3 install ./arbor
+    pip3 install ./arbor --install-option="-DARB_GPU=cuda"
 
 **Enable NVIDIA GPUs (compiled with clang)**. This also requires the :ref:`CUDA toolkit <install-gpu>`:
 
 .. code-block:: bash
 
-    CMAKE_ARGS="-DARB_GPU=cuda-clang" pip3 install ./arbor
+    pip3 install ./arbor --install-option="-DARB_GPU=cuda-clang"
 
 **Enable AMD GPUs (compiled with hipcc)**. This requires setting the ``CC`` and ``CXX``
-:ref:`environment variables <install-gpu>`:
+:ref:`environment variables <install-gpu>`
 
 .. code-block:: bash
 
-    CC=clang CXX=hipcc CMAKE_ARGS="-DARB_GPU=hip" pip3 install ./arbor
+    pip3 install ./arbor --install-option="-DARB_GPU=hip"
 
 Note on performance
 -------------------
diff --git a/pyproject.toml b/pyproject.toml
deleted file mode 100644
index 745f74710d7b01a838aece2d6350d092704554c5..0000000000000000000000000000000000000000
--- a/pyproject.toml
+++ /dev/null
@@ -1,72 +0,0 @@
-[project]
-name = "arbor"
-dynamic = ["version", "readme"]
-license = {file = "LICENSE"}
-description = "High performance simulation of networks of multicompartment neurons."
-requires-python = ">=3.7"
-keywords = ["simulator", "neuroscience", "morphological detail", "HPC", "GPU", "C++"]
-authors = [
-    {name = "Arbor Dev Team", email = "contact@arbor-sim.org"}
-]
-maintainers = [
-    {name = "Arbor Dev Team", email = "contact@arbor-sim.org"}
-]
-classifiers = [
-    "Development Status :: 5 - Production/Stable",
-    "Intended Audience :: Science/Research",
-    "License :: OSI Approved :: BSD License",
-    "Programming Language :: Python",
-    "Programming Language :: Python :: 3.7",
-    "Programming Language :: Python :: 3.8",
-    "Programming Language :: Python :: 3.9",
-    "Programming Language :: Python :: 3.10",
-    "Programming Language :: C++"
-]
-dependencies = [
-    "numpy"
-]
-
-[tool.setuptools]
-py-modules = ["arbor"]
-
-[tool.setuptools.dynamic]
-version = {file = ["VERSION"]}
-readme = {file = ["python/readme.md"]}
-
-[project.urls]
-homepage = "https://arbor-sim.org"
-documentation = "https://docs.arbor-sim.org"
-repository = "https://github.com/arbor-sim/arbor"
-changelog = "https://github.com/arbor-sim/arbor/releases"
-
-[build-system]
-requires = [
-    "setuptools",
-    "wheel",
-    "scikit-build",
-    "cmake>=3.18",
-    "ninja",
-]
-build-backend = "setuptools.build_meta"
-
-[tool.cibuildwheel]
-build-frontend = "build"
-build = ["cp3*-manylinux_x86_64","cp3*-macosx_universal2"]#,"cp3*-musllinux_x86_64","cp3*-musllinux_aarch64"]
-skip = "cp36-*"
-test-command = "python3 -m unittest discover -v -s {project}/python"
-
-[tool.cibuildwheel.macos]
-archs = ["x86_64", "universal2", "arm64"]
-
-[tool.cibuildwheel.macos.environment]
-MACOSX_DEPLOYMENT_TARGET = "10.15"
-
-[tool.cibuildwheel.linux]
-archs = ["x86_64"]
-manylinux-x86_64-image = "manylinux2014"
-before-all = "yum -y install libxml2-devel"
-repair-wheel-command = "auditwheel repair -w {dest_dir} {wheel} && python3 /project/scripts/patchwheel.py {dest_dir}"
-
-[[tool.cibuildwheel.overrides]]
-select = "*-musllinux*"
-before-all = "apk add libxml2-dev"
diff --git a/python/example/single_cell_allen.py b/python/example/single_cell_allen.py
index 359b62e245174ff3d6f461d1a645c3dacd7c9691..eac24649175f0d8d0f8b7e6f66066a4663357e6a 100644
--- a/python/example/single_cell_allen.py
+++ b/python/example/single_cell_allen.py
@@ -1,7 +1,6 @@
 #!/usr/bin/env python3
 
 from collections import defaultdict
-from dataclasses import dataclass
 import json
 import arbor
 import seaborn
@@ -16,12 +15,13 @@ def load_allen_fit(fit):
         fit = json.load(fd)
 
     # cable parameters convenience class
-    @dataclass
     class parameters:
-        cm: float = None
-        tempK: float = None
-        Vm: float = None
-        rL: float = None
+        def __init__(self, **kwargs):
+            self.cm = None
+            self.tempK = None
+            self.Vm = None
+            self.rL = None
+            self.__dict__.update(kwargs)
 
     param = defaultdict(parameters)
     mechs = defaultdict(dict)
diff --git a/scripts/build-wheels.sh b/scripts/build-wheels.sh
index 4b6412da948b8ce2191980cc375f977870b35194..0b881c71b09dfe9fa288056b4270da65dc23be32 100755
--- a/scripts/build-wheels.sh
+++ b/scripts/build-wheels.sh
@@ -14,14 +14,14 @@
 set -e -u -x
 
 yum -y install libxml2-devel
+/opt/python/cp310-cp310/bin/pip install ninja cmake
 
 rm -rf /src_dir/arbor/_skbuild
-rm -rf /opt/python/cp36-cp36m # Python build toolchain does not work on Py3.6
 
 export CIBUILDWHEEL=1 #Set condition for cmake
 
-for PYBIN in /opt/python/cp3*/bin; do
-    "${PYBIN}/python" -m pip install pip auditwheel -U
+for PYBIN in /opt/python/cp*/bin; do
+    "${PYBIN}/python" -m pip install wheel scikit-build auditwheel
     export PATH="${PYBIN}":$PATH
     "${PYBIN}/python" -m pip wheel --wheel-dir="/src_dir/builtwheel${PYBIN}/" /src_dir/arbor
     "${PYBIN}/python" -m auditwheel repair /src_dir/builtwheel${PYBIN}/arbor*.whl -w /src_dir/wheelhouse
diff --git a/setup.py b/setup.py
index 30f9ed589d923cfb63b839faa9aff9ffd2484cc5..7511cd70a39c603025b58be2661f849b74003b78 100644
--- a/setup.py
+++ b/setup.py
@@ -1,3 +1,4 @@
+from pathlib import Path
 from sys import executable as python
 from skbuild import setup
 
@@ -12,7 +13,23 @@ with_nml = True
 use_libs = True
 build_type = "Release"  # this is ok even for debugging, as we always produce info
 
+# Find our dir; *should* be the arbor checkout
+here = Path(__file__).resolve().parent
+# Read version file
+with open(here / "VERSION") as fd:
+    arbor_version = fd.read().strip()
+# Get the contents of the readme
+with open(here / "python" / "readme.md", encoding="utf-8") as fd:
+    long_description = fd.read()
+
 setup(
+    name="arbor",
+    version=arbor_version,
+    python_requires=">=3.6",
+    install_requires=["numpy"],
+    setup_requires=[],
+    zip_safe=False,
+    packages=["arbor"],
     cmake_args=[
         "-DARB_WITH_PYTHON=on",
         f"-DPYTHON_EXECUTABLE={python}",
@@ -24,4 +41,25 @@ setup(
         f"-DARB_USE_BUNDLED_LIBS={use_libs}",
         f"-DCMAKE_BUILD_TYPE={build_type}",
     ],
+    author="The Arbor dev team.",
+    url="https://arbor-sim.org",
+    description="High performance simulation of networks of multicompartment neurons.",
+    long_description=long_description,
+    long_description_content_type="text/markdown",
+    classifiers=[
+        "Development Status :: 5 - Production/Stable",
+        "Intended Audience :: Science/Research",
+        "License :: OSI Approved :: BSD License",
+        "Programming Language :: Python :: 3.6",
+        "Programming Language :: Python :: 3.7",
+        "Programming Language :: Python :: 3.8",
+        "Programming Language :: Python :: 3.9",
+        "Programming Language :: Python :: 3.10",
+        "Programming Language :: C++",
+    ],
+    project_urls={
+        "Source": "https://github.com/arbor-sim/arbor",
+        "Documentation": "https://docs.arbor-sim.org",
+        "Bug Reports": "https://github.com/arbor-sim/arbor/issues",
+    },
 )
diff --git a/spack/package.py b/spack/package.py
index c5028e59f0eff89e7151f1151cc5fdfe22e872ad..016265041e30243c1169edbcf6c83588a6b80512 100644
--- a/spack/package.py
+++ b/spack/package.py
@@ -69,14 +69,14 @@ class Arbor(CMakePackage, CudaPackage):
 
     # python (bindings)
     extends("python", when="+python")
-    depends_on("python@3.7:", when="+python", type=("build", "run"))
+    depends_on("python@3.6:", when="+python", type=("build", "run"))
     depends_on("py-numpy", when="+python", type=("build", "run"))
     with when("+python"):
-        depends_on("py-pybind11@2.6:", type=("build"))
-        depends_on("py-pybind11@2.8.1:", when="@0.5.3:", type=("build"))
+        depends_on("py-pybind11@2.6:", type=("build", "run"))
+        depends_on("py-pybind11@2.8.1:", when="@0.5.3:", type=("build", "run"))
 
     # sphinx based documentation
-    depends_on("python@3.7:", when="+doc", type="build")
+    depends_on("python@3.6:", when="+doc", type="build")
     depends_on("py-sphinx", when="+doc", type="build")
     depends_on("py-svgwrite", when="+doc", type="build")