Repository: DiamondLightSource/aioca (language: python)

Issue:
Hosted documentation doesn't indicate async functions
e.g. https://aioca.readthedocs.io/en/latest/api.html#aioca.caput

And yet if I build it locally the HTML does indicate async functions. Is this a Sphinx version difference?


Discussion / hints:
Yes, readthedocs is on an older version of sphinx. I plan to move to GitHub.io soon...

Fix patch:
diff --git a/.gitattributes b/.gitattributes
index b238f6f..41a1393 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,1 @@
-* module-contact=tmc43
 */_version_git.py export-subst
diff --git a/.github/pages/index.html b/.github/pages/index.html
new file mode 100644
index 0000000..d0f5882
--- /dev/null
+++ b/.github/pages/index.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Redirecting to master branch</title>
+    <meta charset="utf-8">
+    <meta http-equiv="refresh" content="0; url=./master/index.html">
+    <link rel="canonical" href="master/index.html">
+  </head>
+</html>
\ No newline at end of file
diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml
new file mode 100644
index 0000000..0267dd8
--- /dev/null
+++ b/.github/workflows/code.yml
@@ -0,0 +1,87 @@
+name: Code CI
+
+on:
+  push:
+  pull_request:
+
+jobs:
+  build:
+    name: ${{ matrix.os }}/${{ matrix.python }}
+    runs-on: ubuntu-latest
+
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          # DLS RHEL7 python3 current
+          - os: ubuntu-latest
+            python: "3.7"
+            # Deploy wheel from here
+            publish: true
+
+          # Other possibilities
+          - os: ubuntu-latest
+            python: "3.8"
+
+          - os: ubuntu-latest
+            python: "3.9"
+
+          - os: windows-latest
+            python: "3.7"
+
+          - os: windows-latest
+            python: "3.8"
+
+          - os: windows-latest
+            python: "3.9"
+
+          - os: macOS-latest-latest
+            python: "3.7"
+
+          - os: macOS-latest-latest
+            python: "3.8"
+
+          - os: macOS-latest-latest
+            python: "3.9"
+
+    steps:
+      - name: Checkout Source
+        uses: actions/checkout@v2
+
+      - name: Set up Python ${{ matrix.python }}
+        uses: actions/setup-python@v2
+        with:
+          python-version: ${{ matrix.python }}
+
+      - name: Install Python Dependencies
+        run: |
+          env
+          pip install pipenv
+          pipenv install --dev --deploy --python $(which python) && pipenv graph
+
+      - name: Create Sdist and Wheel
+        # for reproducible builds set SOURCE_DATE_EPOCH to the date of the last commit
+        # See here for more info : https://reproducible-builds.org/
+        # Also use the same version of wheel as inside DLS
+        run: |
+          export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
+          pip install "wheel==0.33.1"
+          python setup.py sdist bdist_wheel
+
+      - name: Run Tests
+        run : pipenv run tests --cov-report=xml
+
+      - name: Publish Sdist and Wheel to PyPI
+        # Only once when on a tag
+        if: matrix.publish && startsWith(github.ref, 'refs/tags')
+        # We pin to the SHA, not the tag, for security reasons.
+        # https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
+        uses: pypa/gh-action-pypi-publish@54b39fb9371c0b3a6f9f14bb8a67394defc7a806  # v1.4.1
+        with:
+          user: __token__
+          password: ${{ secrets.pypi_token }}
+
+      - name: Upload coverage to Codecov
+        uses: codecov/codecov-action@v1
+        with:
+          name: ${{ matrix.python }}
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 0000000..0ec5c24
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,66 @@
+name: Docs CI
+
+on:
+  push:
+  pull_request:
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: Checkout Source
+        uses: actions/checkout@v2
+        with:
+          # require all of history to see all tagged versions' docs
+          fetch-depth: 0
+
+      - name: Set up Python
+        uses: actions/setup-python@v2
+        with:
+          python-version: "3.7"
+
+      - name: Install Packages
+        run: sudo apt-get install graphviz
+
+      - name: Install Python Dependencies
+        run: |
+          pip install pipenv
+          pipenv install --dev --deploy --python $(which python) && pipenv graph
+
+      - name: Deploy index
+        # We pin to the SHA, not the tag, for security reasons.
+        # https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
+        uses: peaceiris/actions-gh-pages@bbdfb200618d235585ad98e965f4aafc39b4c501  # v3.7.3
+        with:
+          github_token: ${{ secrets.GITHUB_TOKEN }}
+          publish_dir: .github/pages
+          keep_files: true
+
+      - name: Checkout gh-pages
+        # As we already did a deploy of gh-pages above, it is guaranteed to be there
+        # so check it out so we can selectively build docs below
+        uses: actions/checkout@v2
+        with:
+          ref: gh-pages
+          path: build/html
+
+      - name: Maybe use sphinx-multiversion
+        # If we are building master or a tag we will publish
+        if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags')
+        # So use the args we normally pass to sphinx-build, but run sphinx-multiversion
+        run: mv $(pipenv --venv)/bin/sphinx-multiversion $(pipenv --venv)/bin/sphinx-build
+
+      - name: Build Docs
+        run: pipenv run docs
+
+      - name: Publish Docs to gh-pages
+        # Only master and tags are published
+        if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags')
+        # We pin to the SHA, not the tag, for security reasons.
+        # https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
+        uses: peaceiris/actions-gh-pages@bbdfb200618d235585ad98e965f4aafc39b4c501  # v3.7.3
+        with:
+          github_token: ${{ secrets.GITHUB_TOKEN }}
+          publish_dir: build/html
+          keep_files: true
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index e4dc8c0..0000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-rhel7_job:
-  tags:
-    - rhel7
-  before_script:
-    - pipenv install --dev
-  script:
-    - pipenv run tests
-    - pipenv run docs
-    - dls-python3 setup.py bdist_wheel
-    - dls-py3 check --no-tag-check
diff --git a/.readthedocs.yml b/.readthedocs.yml
deleted file mode 100644
index 425022d..0000000
--- a/.readthedocs.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-# Read the Docs configuration file
-# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
-version: 2
-
-# Set the version of Python and requirements required to build your docs
-python:
-  version: 3.7
-  install:
-    - requirements: docs/requirements.txt
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 115b28b..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,68 +0,0 @@
-env:
-  global:
-    # This sets SOURCE_DATE_EPOCH to the date of the last commit for reproducible builds
-    # See here for more info : https://reproducible-builds.org/
-    - SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
-
-jobs:
-  include:
-
-    - name: "Python 3.7 on Linux"
-      python: 3.7
-      language: python
-      env: PYTHON=python BDIST=bdist_wheel
-
-    - name: "Python 3.8 on Linux"
-      python: 3.8
-      language: python
-      env: PYTHON=python BDIST=bdist_wheel
-
-    - name: "Python 3.7 on macOS"
-      os: osx
-      osx_image: xcode11.2
-      language: shell
-      env: PYTHON=python3 BDIST=bdist_wheel
-
-    - name: "Python 3.7 on Windows"
-      os: windows
-      before_install:
-        - choco install python --version 3.7.6
-      language: shell
-      env: PYTHON=python PATH=/c/Python37:/c/Python37/Scripts:$PATH BDIST=bdist_wininst
-
-    - name: "Python 3.8 on Windows"
-      os: windows
-      before_install:
-        - choco install python --version 3.8.2
-      language: shell
-      env: PYTHON=python PATH=/c/Python38:/c/Python38/Scripts:$PATH BDIST=bdist_wininst
-
-install:
-  - env
-  - which $PYTHON
-  - $PYTHON --version
-  - $PYTHON -m pip install --upgrade pip coveralls pipenv==2018.11.26
-  - pipenv install --dev
-  - $PYTHON setup.py $BDIST
-
-script:
-  - pipenv run tests
-  - pipenv run docs
-
-after_script:
-  - coveralls
-
-deploy:
-  provider: pypi
-  edge: true
-  user: "__token__"
-  password:
-    secure: "1D96l9DQhR55GEuqp4qvYwsERRJcoH2pZkcGwgWYVFmgqQHQFM2/3fcv/c27mi0axda7dgs8m6X8dmBfdKa6mjOmn/nwQl3Hx6BTwCcav/HWJj5OErMotziTOLvu6xvm37uftYT9wWf5CuhJ11re9JSVCumIIncK9cW6UG9laXvJVHK/JT7CKGTafu+wAH/X9Im5527RL+iUxcKdbbyu+jrJlmUnw64ARtBlUkHy6mUh5UuKjJcJxQGtmflclnkHCLyCIuDnoIPr5fwZ8FoTUaaMghYIzPNtsxY0pIMNt63TNTwMdUNh7BzeggJsd4rAW4CpSykZX01IGXaEzzLQCXxNwLI/vxOxY0fgw39ZHh9JZXFD0J1ty1WCl9V4CYILk2Im1JYfNYqXqTX+jTHvyEfAX2tQBbhmA+wI4/riqnbP1OeIMdCqCu9hmqN47rHrvja/56B2h5XqW8fRQtG+XaGZSiQRXScFfTOvvSME8W+X9UBlQ0wAulwNBdYrR4xyl6dwoPJIGk+Ypj+DCBGQK9jpgMfA47CpdFfniVWc7UnV+1Ay7v9ca6sRV9+KiuWuksaZD2kNpDXtN/uzwpcfQakQ23CgWTyAnHdE8UO5UUY2SFjjRbRa8sWGnnue4m+5Md97bUeO5W/xX/fGXz2JkJRABL+GSkfCFxpe2fQzSqQ="
-  distributions: "sdist bdist_wheel"
-  # Use the same version of wheel as inside DLS
-  wheel_version: "0.33.1"
-  skip_existing: true
-  on:
-    tags: true
-    # Only deploy on one Linux as its the same wheel
-    condition: $TRAVIS_JOB_NAME = "Python 3.8 on Linux"    
diff --git a/.vscode/settings.json b/.vscode/settings.json
index dc21d98..b2feaec 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -7,7 +7,8 @@
     "python.testing.nosetestsEnabled": false,
     "python.testing.pytestEnabled": true,
     "python.formatting.provider": "black",
-    "python.languageServer": "Microsoft",
+    "python.languageServer": "Pylance",
     "restructuredtext.confPath": "${workspaceFolder}/docs",
-    "editor.defaultFormatter": null
+    "editor.defaultFormatter": null,
+    "python.pythonPath": "/home/tom/.local/share/virtualenvs/aioca-4YYuDdK-/bin/python"
 }
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index bb1d5f0..ebc7140 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -6,7 +6,7 @@
         {
             "type": "shell",
             "label": "Fix all isort issues",
-            "command": "pipenv run isort -y",
+            "command": "pipenv run isort .",
             "options": {
                 "cwd": "${workspaceRoot}"
             },
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 7d7ee06..b4859df 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -71,6 +71,8 @@ Release Checklist
 
 Before a new release, please go through the following checklist:
 
-* Add a release note in CHANGELOG.rst
-* Git tag the version with message from CHANGELOG
-* Push to github and travis will make a release on pypi
+- Choose a new PEP440 compliant release number
+- Add a release note in CHANGELOG.rst
+- Git tag the version with message from CHANGELOG
+- Push to github and the actions will make a release on pypi
+- Push to internal gitlab and do a dls-release.py of the tag
diff --git a/Pipfile b/Pipfile
index ca57bff..b391412 100644
--- a/Pipfile
+++ b/Pipfile
@@ -4,24 +4,30 @@ url = "https://pypi.org/simple"
 verify_ssl = true
 
 [dev-packages]
+# Pinning black stops us having to allow pre-releases globally
+black = "==19.10b0"
 pytest-cov = "*"
 pytest-mypy = "*"
 pytest-flake8 = "*"
 pytest-black = "*"
 flake8-isort = "*"
+isort = ">5.0"
 sphinx-rtd-theme = "*"
 pytest-asyncio = "*"
-# Pinning black stops us having to allow pre-releases globally
-black = "==19.10b0"
 # Without these lines lockfile isn't usable on multiple Python versions and platforms
 mypy = "*"
+typing-extensions = "*"
 atomicwrites = "*"
-
-[scripts]
-# Put coverage here so we don't interfere with debugging in the IDE
-tests = "python -m pytest --cov-fail-under=90 --cov=aioca --cov-report term"
-docs = "sphinx-build -E -b html docs build/html"
+importlib-metadata = "*"
+# switch to main repo after PR https://github.com/Holzhaus/sphinx-multiversion/pull/60 is merged
+sphinx-multiversion = {editable = true,git = "https://github.com/dls-controls/sphinx-multiversion.git",ref = "only-arg"}
 
 [packages]
 # All other package requirements from setup.cfg
 aioca = {editable = true,path = "."}
+
+[scripts]
+# Put coverage here so we don't interfere with debugging in the IDE
+tests = "python -m pytest --cov=aioca --cov-report term"
+docs = "sphinx-build -EWT --keep-going docs build/html"
+clean = "rm -rf build prefix */__pycache__ .coverage cov.xml *.egg-info .mypy_cache .pytest_cache"
diff --git a/Pipfile.lock b/Pipfile.lock
index 479d422..85aa1b9 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "9c62f7d4312ca55a08ba7e6da8f34e37b2a1e6b635e150d3b0c34a2d12d4a5bd"
+            "sha256": "d7afa2889f96bdeb402a5c2dd217e532896808a820d5c1e59cbc45cc029b145c"
         },
         "pipfile-spec": 6,
         "requires": {},
@@ -20,69 +20,82 @@
         },
         "epicscorelibs": {
             "hashes": [
-                "sha256:00fae0b90cda857b0a2d2c6825fb53eb8ecac4afeb98a0f322736256e4f14739",
-                "sha256:044c933f2771cc49165711a9bc141e9b27867d52773a6f7ab07c0946b6f3a994",
-                "sha256:05af524d3f69d2b648444ef9a28c4f835a7718e5513a2449d52d607f1257cf17",
-                "sha256:0b6d280106a4a278917d5e98ad9f570fdb6169ac313700a3137fb8546bbc0686",
-                "sha256:10226f148ae73acb223cb4b7ea61a02183ea9c1cc7e6c7d4a6afc49842eaaf4f",
-                "sha256:287cb65ee036090d913c3f1e2e53247283f1cf510acbb4ca7ee23036e757a768",
-                "sha256:5d9887dc19dae19884037c1afe0c8a443f0a1d9c871a48612f63bcf814e7a448",
-                "sha256:60e273c3f9ec72a6613e507d566e92aa645380006743615fe8f352431d130a67",
-                "sha256:6ce6681866b548c104f0368b3b85e75e0eb5057467cf97d496e5a53526f3fda9",
-                "sha256:7dc7de870758651642fef2773e691238ce8c4a0720bbd345477b7cf26c85f537",
-                "sha256:8b6d41bd8962a3f62c2380847c408e3acc4bda54f60457a45f9aba6cca1bd9c4",
-                "sha256:9f415bd216b05c25ab44fc4ebfe0da5ab1a5b14e89a699f11eff367404cca2a7",
-                "sha256:a08d501a3a779fa466bff824dfedad008b0f33160a5fd3252e451b9f0922bd47",
-                "sha256:b2a14ff67a9690bf468218d7b22ec38acd147b93e1800cb3d762f0bb098ac585",
-                "sha256:b678995a88a06338599148ab7fcc73f00cdb2f73b4dd5160b76ac31393465bdb",
-                "sha256:bf6e68da71374d806a710058f845d79a44af54c1352c84868323d15efc521735",
-                "sha256:c5549bec4d4899037028ebf50ca4ce4549b26555af5b99237628f12b6d3938ee",
-                "sha256:cd1e69849bb33e23c94ecd23e40100990b2df5be2b3465f5803190affaea1217",
-                "sha256:d668bfcae6f5fcf2ee06d268186e2115c7ca51ac20716e419ff7c09ab8b24808",
-                "sha256:dce2d2f4500fb006c632cb7a3f503bff093c9a91f3e60e68df31648dccf65289",
-                "sha256:def6ea91f8ca5b40b7d1e8188c582ae192c5939f64a74dc9a44f9eed63466072",
-                "sha256:df8a520e35837c31ee4c4e6fd269069e2a58926cc6d99066910d729368565ea4",
-                "sha256:ecb3e9d2da8c1ddd935febcee9bd6b927bc64791061d2a24f74f784912b82496",
-                "sha256:ed80591589509a83a46509cd20dacf6a8f1a0018fae65b1ee6dbf22201d4fab5",
-                "sha256:ef300463421cc3420d6f88e191fcc7533c814c207cd17dcf343e4c99ad398da6",
-                "sha256:f35f5ff2e9c5c1bff03220f680145016c53f2adc21e15877d6a40e345feaba47",
-                "sha256:f8a5cd26dbb4152ac156b7a93ccf82a8da6a92a69801d1f3251c8fd39d19623f"
-            ],
-            "version": "==7.0.3.99.4.0"
+                "sha256:0fa5dc4fe3762b8e1380e1e9ebcff4d21506a89c635cb49c00c0be9c65663279",
+                "sha256:15bdbeda1e445f13f5e94bf6665cbffebd76b461d2bfb782d453166ad93a6e4e",
+                "sha256:16257b172e55cdbff2b7fe8ecc48d00e782e714996c01fd3ef63abbcfec4f6fd",
+                "sha256:1bb8cb3a810b1c60be7c8ee060840eb9b5b6ba24337473b7ce072ea70470a8a9",
+                "sha256:2497532712a608dba29a0da07e094d425e3eda3e3a29c5ee3f3931b1dd78277b",
+                "sha256:2bedc3915709119c6bf8cdd40bf30682570ee24308556ce5d7b8658804c4da38",
+                "sha256:31c7e298498a78ea4d1ac5eb3d1d794df3fb62c54e44ba5d489a1a6771f416a1",
+                "sha256:350f540864f642be73ea0a12c52520b2c050e65027e21ce3c5293f5cbfea3b20",
+                "sha256:3748d0f7e04190ea3910d552a8915f3572f4f50fa9e231f8e03a14b01362ae79",
+                "sha256:4190673b94c3021bb0493484f7128b45c055af47ecb34433a913c5dd496f56e7",
+                "sha256:51bf0e1118125ba7d8c485b515579cd1210024a876eaa65d1084f51278414476",
+                "sha256:5f6e2d9ffb3e89e48115dae36c532aded656c047840b6788d55afbd009399a30",
+                "sha256:5fade32ea523f2ace0021d973046460c4baaa4ca8ea4d4523299e14c6f42cf4e",
+                "sha256:88a4695f807207f19e9d38084df5c799c8998c3ba7f63b81de5f2d7370a64d8b",
+                "sha256:9e8ffda8298698b83fd6a3f728ec1574de4f442145462951a2a96ea3e3a165e5",
+                "sha256:a84b5a7a17963d5bba02c7cdc536cf1dd7d66fa600aaca09a0d6c2425c069db3",
+                "sha256:ac5296922499c8a5090a1b1f5d1ab36b6472d99bb93c0fdcd7885eefb798f031",
+                "sha256:b031ef91321daa3eb30120d8a2e55aa7545480038e76655ac0fe386966260f0d",
+                "sha256:b86592c6777d877af1168c71b07476d30514334837523e0b34c73a0e99f594d7",
+                "sha256:e004f31e74397bc1c6a8b313570620ac14272a9867a11dcd8be5a4a9a10bec85",
+                "sha256:e18ba8f3979a7f69b22069445eb76733829f40706153bdc2d62e6cbc4d4634f4",
+                "sha256:e2435e8774669f623dd70688b6b3f884cd150a744186fba544b0d867468a6a7e",
+                "sha256:e33f3fc053238b751e33de97d3d163c6dabfcf4202b477e353542300d69f6c1f",
+                "sha256:e8cc04309f8b885c61bc0e6562a2af80c097f295d3dbb6e375e5bc80717d6e53",
+                "sha256:f2c8a85042aae0bf5b949d0aedfdf4ed08ea8498c1d25019c7f5c671708d87d2"
+            ],
+            "markers": "python_version >= '2.7'",
+            "version": "==7.0.4.99.1.2"
         },
         "numpy": {
             "hashes": [
-                "sha256:00d7b54c025601e28f468953d065b9b121ddca7fff30bed7be082d3656dd798d",
-                "sha256:02ec9582808c4e48be4e93cd629c855e644882faf704bc2bd6bbf58c08a2a897",
-                "sha256:0e6f72f7bb08f2f350ed4408bb7acdc0daba637e73bce9f5ea2b207039f3af88",
-                "sha256:1be2e96314a66f5f1ce7764274327fd4fb9da58584eaff00b5a5221edefee7d6",
-                "sha256:2466fbcf23711ebc5daa61d28ced319a6159b260a18839993d871096d66b93f7",
-                "sha256:2b573fcf6f9863ce746e4ad00ac18a948978bb3781cffa4305134d31801f3e26",
-                "sha256:3f0dae97e1126f529ebb66f3c63514a0f72a177b90d56e4bce8a0b5def34627a",
-                "sha256:50fb72bcbc2cf11e066579cb53c4ca8ac0227abb512b6cbc1faa02d1595a2a5d",
-                "sha256:57aea170fb23b1fd54fa537359d90d383d9bf5937ee54ae8045a723caa5e0961",
-                "sha256:709c2999b6bd36cdaf85cf888d8512da7433529f14a3689d6e37ab5242e7add5",
-                "sha256:7d59f21e43bbfd9a10953a7e26b35b6849d888fc5a331fa84a2d9c37bd9fe2a2",
-                "sha256:904b513ab8fbcbdb062bed1ce2f794ab20208a1b01ce9bd90776c6c7e7257032",
-                "sha256:96dd36f5cdde152fd6977d1bbc0f0561bccffecfde63cd397c8e6033eb66baba",
-                "sha256:9933b81fecbe935e6a7dc89cbd2b99fea1bf362f2790daf9422a7bb1dc3c3085",
-                "sha256:bbcc85aaf4cd84ba057decaead058f43191cc0e30d6bc5d44fe336dc3d3f4509",
-                "sha256:dccd380d8e025c867ddcb2f84b439722cf1f23f3a319381eac45fd077dee7170",
-                "sha256:e22cd0f72fc931d6abc69dc7764484ee20c6a60b0d0fee9ce0426029b1c1bdae",
-                "sha256:ed722aefb0ebffd10b32e67f48e8ac4c5c4cf5d3a785024fdf0e9eb17529cd9d",
-                "sha256:efb7ac5572c9a57159cf92c508aad9f856f1cb8e8302d7fdb99061dbe52d712c",
-                "sha256:efdba339fffb0e80fcc19524e4fdbda2e2b5772ea46720c44eaac28096d60720",
-                "sha256:f22273dd6a403ed870207b853a856ff6327d5cbce7a835dfa0645b3fc00273ec"
-            ],
-            "version": "==1.18.4"
+                "sha256:012426a41bc9ab63bb158635aecccc7610e3eff5d31d1eb43bc099debc979d94",
+                "sha256:06fab248a088e439402141ea04f0fffb203723148f6ee791e9c75b3e9e82f080",
+                "sha256:0eef32ca3132a48e43f6a0f5a82cb508f22ce5a3d6f67a8329c81c8e226d3f6e",
+                "sha256:1ded4fce9cfaaf24e7a0ab51b7a87be9038ea1ace7f34b841fe3b6894c721d1c",
+                "sha256:2e55195bc1c6b705bfd8ad6f288b38b11b1af32f3c8289d6c50d47f950c12e76",
+                "sha256:2ea52bd92ab9f768cc64a4c3ef8f4b2580a17af0a5436f6126b08efbd1838371",
+                "sha256:36674959eed6957e61f11c912f71e78857a8d0604171dfd9ce9ad5cbf41c511c",
+                "sha256:384ec0463d1c2671170901994aeb6dce126de0a95ccc3976c43b0038a37329c2",
+                "sha256:39b70c19ec771805081578cc936bbe95336798b7edf4732ed102e7a43ec5c07a",
+                "sha256:400580cbd3cff6ffa6293df2278c75aef2d58d8d93d3c5614cd67981dae68ceb",
+                "sha256:43d4c81d5ffdff6bae58d66a3cd7f54a7acd9a0e7b18d97abb255defc09e3140",
+                "sha256:50a4a0ad0111cc1b71fa32dedd05fa239f7fb5a43a40663269bb5dc7877cfd28",
+                "sha256:603aa0706be710eea8884af807b1b3bc9fb2e49b9f4da439e76000f3b3c6ff0f",
+                "sha256:6149a185cece5ee78d1d196938b2a8f9d09f5a5ebfbba66969302a778d5ddd1d",
+                "sha256:759e4095edc3c1b3ac031f34d9459fa781777a93ccc633a472a5468587a190ff",
+                "sha256:7fb43004bce0ca31d8f13a6eb5e943fa73371381e53f7074ed21a4cb786c32f8",
+                "sha256:811daee36a58dc79cf3d8bdd4a490e4277d0e4b7d103a001a4e73ddb48e7e6aa",
+                "sha256:8b5e972b43c8fc27d56550b4120fe6257fdc15f9301914380b27f74856299fea",
+                "sha256:99abf4f353c3d1a0c7a5f27699482c987cf663b1eac20db59b8c7b061eabd7fc",
+                "sha256:a0d53e51a6cb6f0d9082decb7a4cb6dfb33055308c4c44f53103c073f649af73",
+                "sha256:a12ff4c8ddfee61f90a1633a4c4afd3f7bcb32b11c52026c92a12e1325922d0d",
+                "sha256:a4646724fba402aa7504cd48b4b50e783296b5e10a524c7a6da62e4a8ac9698d",
+                "sha256:a76f502430dd98d7546e1ea2250a7360c065a5fdea52b2dffe8ae7180909b6f4",
+                "sha256:a9d17f2be3b427fbb2bce61e596cf555d6f8a56c222bd2ca148baeeb5e5c783c",
+                "sha256:ab83f24d5c52d60dbc8cd0528759532736b56db58adaa7b5f1f76ad551416a1e",
+                "sha256:aeb9ed923be74e659984e321f609b9ba54a48354bfd168d21a2b072ed1e833ea",
+                "sha256:c843b3f50d1ab7361ca4f0b3639bf691569493a56808a0b0c54a051d260b7dbd",
+                "sha256:cae865b1cae1ec2663d8ea56ef6ff185bad091a5e33ebbadd98de2cfa3fa668f",
+                "sha256:cc6bd4fd593cb261332568485e20a0712883cf631f6f5e8e86a52caa8b2b50ff",
+                "sha256:cf2402002d3d9f91c8b01e66fbb436a4ed01c6498fffed0e4c7566da1d40ee1e",
+                "sha256:d051ec1c64b85ecc69531e1137bb9751c6830772ee5c1c426dbcfe98ef5788d7",
+                "sha256:d6631f2e867676b13026e2846180e2c13c1e11289d67da08d71cacb2cd93d4aa",
+                "sha256:dbd18bcf4889b720ba13a27ec2f2aac1981bd41203b3a3b27ba7a33f88ae4827",
+                "sha256:df609c82f18c5b9f6cb97271f03315ff0dbe481a2a02e56aeb1b1a985ce38e60"
+            ],
+            "markers": "python_version >= '3.7'",
+            "version": "==1.19.5"
         },
         "typing-extensions": {
             "hashes": [
-                "sha256:091ecc894d5e908ac75209f10d5b4f118fbdb2eb1ede6a63544054bb1edb41f2",
-                "sha256:910f4656f54de5993ad9304959ce9bb903f90aadc7c67a0bef07e678014e892d",
-                "sha256:cf8b63fedea4d89bab840ecbb93e75578af28f76f66c35889bd7065f5af88575"
+                "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918",
+                "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c",
+                "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"
             ],
-            "version": "==3.7.4.1"
+            "version": "==3.7.4.3"
         }
     },
     "develop": {
@@ -95,31 +108,32 @@
         },
         "appdirs": {
             "hashes": [
-                "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92",
-                "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"
+                "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41",
+                "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"
             ],
-            "version": "==1.4.3"
+            "version": "==1.4.4"
         },
         "atomicwrites": {
             "hashes": [
-                "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4"
+                "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197",
+                "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"
             ],
             "index": "pypi",
-            "version": "==1.3.0"
+            "version": "==1.4.0"
         },
         "attrs": {
             "hashes": [
-                "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c",
-                "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"
+                "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6",
+                "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"
             ],
-            "version": "==19.3.0"
+            "version": "==20.3.0"
         },
         "babel": {
             "hashes": [
-                "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38",
-                "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4"
+                "sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5",
+                "sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05"
             ],
-            "version": "==2.8.0"
+            "version": "==2.9.0"
         },
         "black": {
             "hashes": [
@@ -131,60 +145,78 @@
         },
         "certifi": {
             "hashes": [
-                "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304",
-                "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"
+                "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c",
+                "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"
             ],
-            "version": "==2020.4.5.1"
+            "version": "==2020.12.5"
         },
         "chardet": {
             "hashes": [
-                "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
-                "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+                "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa",
+                "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"
             ],
-            "version": "==3.0.4"
+            "version": "==4.0.0"
         },
         "click": {
             "hashes": [
-                "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc",
-                "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"
+                "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
+                "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"
             ],
-            "version": "==7.1.1"
+            "version": "==7.1.2"
         },
         "coverage": {
             "hashes": [
-                "sha256:03f630aba2b9b0d69871c2e8d23a69b7fe94a1e2f5f10df5049c0df99db639a0",
-                "sha256:046a1a742e66d065d16fb564a26c2a15867f17695e7f3d358d7b1ad8a61bca30",
-                "sha256:0a907199566269e1cfa304325cc3b45c72ae341fbb3253ddde19fa820ded7a8b",
-                "sha256:165a48268bfb5a77e2d9dbb80de7ea917332a79c7adb747bd005b3a07ff8caf0",
-                "sha256:1b60a95fc995649464e0cd48cecc8288bac5f4198f21d04b8229dc4097d76823",
-                "sha256:1f66cf263ec77af5b8fe14ef14c5e46e2eb4a795ac495ad7c03adc72ae43fafe",
-                "sha256:2e08c32cbede4a29e2a701822291ae2bc9b5220a971bba9d1e7615312efd3037",
-                "sha256:3844c3dab800ca8536f75ae89f3cf566848a3eb2af4d9f7b1103b4f4f7a5dad6",
-                "sha256:408ce64078398b2ee2ec08199ea3fcf382828d2f8a19c5a5ba2946fe5ddc6c31",
-                "sha256:443be7602c790960b9514567917af538cac7807a7c0c0727c4d2bbd4014920fd",
-                "sha256:4482f69e0701139d0f2c44f3c395d1d1d37abd81bfafbf9b6efbe2542679d892",
-                "sha256:4a8a259bf990044351baf69d3b23e575699dd60b18460c71e81dc565f5819ac1",
-                "sha256:513e6526e0082c59a984448f4104c9bf346c2da9961779ede1fc458e8e8a1f78",
-                "sha256:5f587dfd83cb669933186661a351ad6fc7166273bc3e3a1531ec5c783d997aac",
-                "sha256:62061e87071497951155cbccee487980524d7abea647a1b2a6eb6b9647df9006",
-                "sha256:641e329e7f2c01531c45c687efcec8aeca2a78a4ff26d49184dce3d53fc35014",
-                "sha256:65a7e00c00472cd0f59ae09d2fb8a8aaae7f4a0cf54b2b74f3138d9f9ceb9cb2",
-                "sha256:6ad6ca45e9e92c05295f638e78cd42bfaaf8ee07878c9ed73e93190b26c125f7",
-                "sha256:73aa6e86034dad9f00f4bbf5a666a889d17d79db73bc5af04abd6c20a014d9c8",
-                "sha256:7c9762f80a25d8d0e4ab3cb1af5d9dffbddb3ee5d21c43e3474c84bf5ff941f7",
-                "sha256:85596aa5d9aac1bf39fe39d9fa1051b0f00823982a1de5766e35d495b4a36ca9",
-                "sha256:86a0ea78fd851b313b2e712266f663e13b6bc78c2fb260b079e8b67d970474b1",
-                "sha256:8a620767b8209f3446197c0e29ba895d75a1e272a36af0786ec70fe7834e4307",
-                "sha256:922fb9ef2c67c3ab20e22948dcfd783397e4c043a5c5fa5ff5e9df5529074b0a",
-                "sha256:9fad78c13e71546a76c2f8789623eec8e499f8d2d799f4b4547162ce0a4df435",
-                "sha256:a37c6233b28e5bc340054cf6170e7090a4e85069513320275a4dc929144dccf0",
-                "sha256:c3fc325ce4cbf902d05a80daa47b645d07e796a80682c1c5800d6ac5045193e5",
-                "sha256:cda33311cb9fb9323958a69499a667bd728a39a7aa4718d7622597a44c4f1441",
-                "sha256:db1d4e38c9b15be1521722e946ee24f6db95b189d1447fa9ff18dd16ba89f732",
-                "sha256:eda55e6e9ea258f5e4add23bcf33dc53b2c319e70806e180aecbff8d90ea24de",
-                "sha256:f372cdbb240e09ee855735b9d85e7f50730dcfb6296b74b95a3e5dea0615c4c1"
-            ],
-            "version": "==5.0.4"
+                "sha256:03ed2a641e412e42cc35c244508cf186015c217f0e4d496bf6d7078ebe837ae7",
+                "sha256:04b14e45d6a8e159c9767ae57ecb34563ad93440fc1b26516a89ceb5b33c1ad5",
+                "sha256:0cdde51bfcf6b6bd862ee9be324521ec619b20590787d1655d005c3fb175005f",
+                "sha256:0f48fc7dc82ee14aeaedb986e175a429d24129b7eada1b7e94a864e4f0644dde",
+                "sha256:107d327071061fd4f4a2587d14c389a27e4e5c93c7cba5f1f59987181903902f",
+                "sha256:1375bb8b88cb050a2d4e0da901001347a44302aeadb8ceb4b6e5aa373b8ea68f",
+                "sha256:14a9f1887591684fb59fdba8feef7123a0da2424b0652e1b58dd5b9a7bb1188c",
+                "sha256:16baa799ec09cc0dcb43a10680573269d407c159325972dd7114ee7649e56c66",
+                "sha256:1b811662ecf72eb2d08872731636aee6559cae21862c36f74703be727b45df90",
+                "sha256:1ccae21a076d3d5f471700f6d30eb486da1626c380b23c70ae32ab823e453337",
+                "sha256:2f2cf7a42d4b7654c9a67b9d091ec24374f7c58794858bff632a2039cb15984d",
+                "sha256:322549b880b2d746a7672bf6ff9ed3f895e9c9f108b714e7360292aa5c5d7cf4",
+                "sha256:32ab83016c24c5cf3db2943286b85b0a172dae08c58d0f53875235219b676409",
+                "sha256:3fe50f1cac369b02d34ad904dfe0771acc483f82a1b54c5e93632916ba847b37",
+                "sha256:4a780807e80479f281d47ee4af2eb2df3e4ccf4723484f77da0bb49d027e40a1",
+                "sha256:4a8eb7785bd23565b542b01fb39115a975fefb4a82f23d407503eee2c0106247",
+                "sha256:5bee3970617b3d74759b2d2df2f6a327d372f9732f9ccbf03fa591b5f7581e39",
+                "sha256:60a3307a84ec60578accd35d7f0c71a3a971430ed7eca6567399d2b50ef37b8c",
+                "sha256:6625e52b6f346a283c3d563d1fd8bae8956daafc64bb5bbd2b8f8a07608e3994",
+                "sha256:66a5aae8233d766a877c5ef293ec5ab9520929c2578fd2069308a98b7374ea8c",
+                "sha256:68fb816a5dd901c6aff352ce49e2a0ffadacdf9b6fae282a69e7a16a02dad5fb",
+                "sha256:6b588b5cf51dc0fd1c9e19f622457cc74b7d26fe295432e434525f1c0fae02bc",
+                "sha256:6c4d7165a4e8f41eca6b990c12ee7f44fef3932fac48ca32cecb3a1b2223c21f",
+                "sha256:6d2e262e5e8da6fa56e774fb8e2643417351427604c2b177f8e8c5f75fc928ca",
+                "sha256:6d9c88b787638a451f41f97446a1c9fd416e669b4d9717ae4615bd29de1ac135",
+                "sha256:755c56beeacac6a24c8e1074f89f34f4373abce8b662470d3aa719ae304931f3",
+                "sha256:7e40d3f8eb472c1509b12ac2a7e24158ec352fc8567b77ab02c0db053927e339",
+                "sha256:812eaf4939ef2284d29653bcfee9665f11f013724f07258928f849a2306ea9f9",
+                "sha256:84df004223fd0550d0ea7a37882e5c889f3c6d45535c639ce9802293b39cd5c9",
+                "sha256:859f0add98707b182b4867359e12bde806b82483fb12a9ae868a77880fc3b7af",
+                "sha256:87c4b38288f71acd2106f5d94f575bc2136ea2887fdb5dfe18003c881fa6b370",
+                "sha256:89fc12c6371bf963809abc46cced4a01ca4f99cba17be5e7d416ed7ef1245d19",
+                "sha256:9564ac7eb1652c3701ac691ca72934dd3009997c81266807aef924012df2f4b3",
+                "sha256:9754a5c265f991317de2bac0c70a746efc2b695cf4d49f5d2cddeac36544fb44",
+                "sha256:a565f48c4aae72d1d3d3f8e8fb7218f5609c964e9c6f68604608e5958b9c60c3",
+                "sha256:a636160680c6e526b84f85d304e2f0bb4e94f8284dd765a1911de9a40450b10a",
+                "sha256:a839e25f07e428a87d17d857d9935dd743130e77ff46524abb992b962eb2076c",
+                "sha256:b62046592b44263fa7570f1117d372ae3f310222af1fc1407416f037fb3af21b",
+                "sha256:b7f7421841f8db443855d2854e25914a79a1ff48ae92f70d0a5c2f8907ab98c9",
+                "sha256:ba7ca81b6d60a9f7a0b4b4e175dcc38e8fef4992673d9d6e6879fd6de00dd9b8",
+                "sha256:bb32ca14b4d04e172c541c69eec5f385f9a075b38fb22d765d8b0ce3af3a0c22",
+                "sha256:c0ff1c1b4d13e2240821ef23c1efb1f009207cb3f56e16986f713c2b0e7cd37f",
+                "sha256:c669b440ce46ae3abe9b2d44a913b5fd86bb19eb14a8701e88e3918902ecd345",
+                "sha256:c67734cff78383a1f23ceba3b3239c7deefc62ac2b05fa6a47bcd565771e5880",
+                "sha256:c6809ebcbf6c1049002b9ac09c127ae43929042ec1f1dbd8bb1615f7cd9f70a0",
+                "sha256:cd601187476c6bed26a0398353212684c427e10a903aeafa6da40c63309d438b",
+                "sha256:ebfa374067af240d079ef97b8064478f3bf71038b78b017eb6ec93ede1b6bcec",
+                "sha256:fbb17c0d0822684b7d6c09915677a32319f16ff1115df5ec05bdcaaee40b35f3",
+                "sha256:fff1f3a586246110f34dc762098b5afd2de88de507559e63553d7da643053786"
+            ],
+            "version": "==5.4"
         },
         "docutils": {
             "hashes": [
@@ -193,13 +225,6 @@
             ],
             "version": "==0.16"
         },
-        "entrypoints": {
-            "hashes": [
-                "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19",
-                "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"
-            ],
-            "version": "==0.3"
-        },
         "filelock": {
             "hashes": [
                 "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59",
@@ -209,25 +234,25 @@
         },
         "flake8": {
             "hashes": [
-                "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb",
-                "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca"
+                "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839",
+                "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"
             ],
-            "version": "==3.7.9"
+            "version": "==3.8.4"
         },
         "flake8-isort": {
             "hashes": [
-                "sha256:3ce227b5c5342b6d63937d3863e8de8783ae21863cb035cf992cdb0ba5990aa3",
-                "sha256:f5322a85cea89998e0df954162fd35a1f1e5b5eb4fc0c79b5975aa2799106baa"
+                "sha256:2b91300f4f1926b396c2c90185844eb1a3d5ec39ea6138832d119da0a208f4d9",
+                "sha256:729cd6ef9ba3659512dee337687c05d79c78e1215fdf921ed67e5fe46cce2f3c"
             ],
             "index": "pypi",
-            "version": "==3.0.0"
+            "version": "==4.0.0"
         },
         "idna": {
             "hashes": [
-                "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
-                "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"
+                "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
+                "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
             ],
-            "version": "==2.9"
+            "version": "==2.10"
         },
         "imagesize": {
             "hashes": [
@@ -238,28 +263,33 @@
         },
         "importlib-metadata": {
             "hashes": [
-                "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f",
-                "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"
+                "sha256:ace61d5fc652dc280e7b6b4ff732a9c2d40db2c0f92bc6cb74e07b73d53a1771",
+                "sha256:fa5daa4477a7414ae34e95942e4dd07f62adf589143c875c133c1e53c4eff38d"
             ],
-            "markers": "python_version < '3.8'",
-            "version": "==1.6.0"
+            "index": "pypi",
+            "version": "==3.4.0"
         },
-        "isort": {
-            "extras": [
-                "pyproject"
+        "iniconfig": {
+            "hashes": [
+                "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
+                "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"
             ],
+            "version": "==1.1.1"
+        },
+        "isort": {
             "hashes": [
-                "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1",
-                "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"
+                "sha256:c729845434366216d320e936b8ad6f9d681aab72dc7cbc2d51bedc3582f3ad1e",
+                "sha256:fff4f0c04e1825522ce6949973e83110a6e907750cd92d128b0d14aaaadbffdc"
             ],
-            "version": "==4.3.21"
+            "index": "pypi",
+            "version": "==5.7.0"
         },
         "jinja2": {
             "hashes": [
-                "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
-                "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
+                "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419",
+                "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"
             ],
-            "version": "==2.10.1"
+            "version": "==2.11.3"
         },
         "markupsafe": {
             "hashes": [
@@ -306,32 +336,33 @@
             ],
             "version": "==0.6.1"
         },
-        "more-itertools": {
-            "hashes": [
-                "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c",
-                "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507"
-            ],
-            "version": "==8.2.0"
-        },
         "mypy": {
             "hashes": [
-                "sha256:15b948e1302682e3682f11f50208b726a246ab4e6c1b39f9264a8796bb416aa2",
-                "sha256:219a3116ecd015f8dca7b5d2c366c973509dfb9a8fc97ef044a36e3da66144a1",
-                "sha256:3b1fc683fb204c6b4403a1ef23f0b1fac8e4477091585e0c8c54cbdf7d7bb164",
-                "sha256:3beff56b453b6ef94ecb2996bea101a08f1f8a9771d3cbf4988a61e4d9973761",
-                "sha256:7687f6455ec3ed7649d1ae574136835a4272b65b3ddcf01ab8704ac65616c5ce",
-                "sha256:7ec45a70d40ede1ec7ad7f95b3c94c9cf4c186a32f6bacb1795b60abd2f9ef27",
-                "sha256:86c857510a9b7c3104cf4cde1568f4921762c8f9842e987bc03ed4f160925754",
-                "sha256:8a627507ef9b307b46a1fea9513d5c98680ba09591253082b4c48697ba05a4ae",
-                "sha256:8dfb69fbf9f3aeed18afffb15e319ca7f8da9642336348ddd6cab2713ddcf8f9",
-                "sha256:a34b577cdf6313bf24755f7a0e3f3c326d5c1f4fe7422d1d06498eb25ad0c600",
-                "sha256:a8ffcd53cb5dfc131850851cc09f1c44689c2812d0beb954d8138d4f5fc17f65",
-                "sha256:b90928f2d9eb2f33162405f32dde9f6dcead63a0971ca8a1b50eb4ca3e35ceb8",
-                "sha256:c56ffe22faa2e51054c5f7a3bc70a370939c2ed4de308c690e7949230c995913",
-                "sha256:f91c7ae919bbc3f96cd5e5b2e786b2b108343d1d7972ea130f7de27fdd547cf3"
+                "sha256:0d0a87c0e7e3a9becdfbe936c981d32e5ee0ccda3e0f07e1ef2c3d1a817cf73e",
+                "sha256:25adde9b862f8f9aac9d2d11971f226bd4c8fbaa89fb76bdadb267ef22d10064",
+                "sha256:28fb5479c494b1bab244620685e2eb3c3f988d71fd5d64cc753195e8ed53df7c",
+                "sha256:2f9b3407c58347a452fc0736861593e105139b905cca7d097e413453a1d650b4",
+                "sha256:33f159443db0829d16f0a8d83d94df3109bb6dd801975fe86bacb9bf71628e97",
+                "sha256:3f2aca7f68580dc2508289c729bd49ee929a436208d2b2b6aab15745a70a57df",
+                "sha256:499c798053cdebcaa916eef8cd733e5584b5909f789de856b482cd7d069bdad8",
+                "sha256:4eec37370483331d13514c3f55f446fc5248d6373e7029a29ecb7b7494851e7a",
+                "sha256:552a815579aa1e995f39fd05dde6cd378e191b063f031f2acfe73ce9fb7f9e56",
+                "sha256:5873888fff1c7cf5b71efbe80e0e73153fe9212fafdf8e44adfe4c20ec9f82d7",
+                "sha256:61a3d5b97955422964be6b3baf05ff2ce7f26f52c85dd88db11d5e03e146a3a6",
+                "sha256:674e822aa665b9fd75130c6c5f5ed9564a38c6cea6a6432ce47eafb68ee578c5",
+                "sha256:7ce3175801d0ae5fdfa79b4f0cfed08807af4d075b402b7e294e6aa72af9aa2a",
+                "sha256:9743c91088d396c1a5a3c9978354b61b0382b4e3c440ce83cf77994a43e8c521",
+                "sha256:9f94aac67a2045ec719ffe6111df543bac7874cee01f41928f6969756e030564",
+                "sha256:a26f8ec704e5a7423c8824d425086705e381b4f1dfdef6e3a1edab7ba174ec49",
+                "sha256:abf7e0c3cf117c44d9285cc6128856106183938c68fd4944763003decdcfeb66",
+                "sha256:b09669bcda124e83708f34a94606e01b614fa71931d356c1f1a5297ba11f110a",
+                "sha256:cd07039aa5df222037005b08fbbfd69b3ab0b0bd7a07d7906de75ae52c4e3119",
+                "sha256:d23e0ea196702d918b60c8288561e722bf437d82cb7ef2edcd98cfa38905d506",
+                "sha256:d65cc1df038ef55a99e617431f0553cd77763869eebdf9042403e16089fe746c",
+                "sha256:d7da2e1d5f558c37d6e8c1246f1aec1e7349e4913d8fb3cb289a35de573fe2eb"
             ],
             "index": "pypi",
-            "version": "==0.770"
+            "version": "==0.812"
         },
         "mypy-extensions": {
             "hashes": [
@@ -342,17 +373,17 @@
         },
         "packaging": {
             "hashes": [
-                "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3",
-                "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"
+                "sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858",
+                "sha256:78598185a7008a470d64526a8059de9aaa449238f280fc9eb6b13ba6c4109093"
             ],
-            "version": "==20.3"
+            "version": "==20.8"
         },
         "pathspec": {
             "hashes": [
-                "sha256:163b0632d4e31cef212976cf57b43d9fd6b0bac6e67c26015d611a647d5e7424",
-                "sha256:562aa70af2e0d434367d9790ad37aed893de47f1693e4201fd1d3dca15d19b96"
+                "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd",
+                "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"
             ],
-            "version": "==0.7.0"
+            "version": "==0.8.1"
         },
         "pluggy": {
             "hashes": [
@@ -363,31 +394,31 @@
         },
         "py": {
             "hashes": [
-                "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa",
-                "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"
+                "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3",
+                "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"
             ],
-            "version": "==1.8.1"
+            "version": "==1.10.0"
         },
         "pycodestyle": {
             "hashes": [
-                "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56",
-                "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c"
+                "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367",
+                "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"
             ],
-            "version": "==2.5.0"
+            "version": "==2.6.0"
         },
         "pyflakes": {
             "hashes": [
-                "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0",
-                "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"
+                "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92",
+                "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"
             ],
-            "version": "==2.1.1"
+            "version": "==2.2.0"
         },
         "pygments": {
             "hashes": [
-                "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44",
-                "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324"
+                "sha256:bc9591213a8f0e0ca1a5e68a479b4887fdc3e75d0774e5c71c31920c427de435",
+                "sha256:df49d09b498e83c1a73128295860250b0b7edd4c723a32e9bc0d295c7c2ec337"
             ],
-            "version": "==2.6.1"
+            "version": "==2.7.4"
         },
         "pyparsing": {
             "hashes": [
@@ -398,119 +429,136 @@
         },
         "pytest": {
             "hashes": [
-                "sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172",
-                "sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970"
+                "sha256:9d1edf9e7d0b84d72ea3dbcdfd22b35fb543a5e8f2a60092dd578936bf63d7f9",
+                "sha256:b574b57423e818210672e07ca1fa90aaf194a4f63f3ab909a2c67ebb22913839"
             ],
-            "markers": "python_version >= '3.5'",
-            "version": "==5.4.1"
+            "version": "==6.2.2"
         },
         "pytest-asyncio": {
             "hashes": [
-                "sha256:9fac5100fd716cbecf6ef89233e8590a4ad61d729d1732e0a96b84182df1daaf",
-                "sha256:d734718e25cfc32d2bf78d346e99d33724deeba774cc4afdf491530c6184b63b"
+                "sha256:2eae1e34f6c68fc0a9dc12d4bea190483843ff4708d24277c41568d6b6044f1d",
+                "sha256:9882c0c6b24429449f5f969a5158b528f39bde47dc32e85b9f0403965017e700"
             ],
             "index": "pypi",
-            "version": "==0.10.0"
+            "version": "==0.14.0"
         },
         "pytest-black": {
             "hashes": [
-                "sha256:5f3c0cfee9b41e6281a9e52e2987f4c90ec4a13a92bbf2f249d26d7b58747437"
+                "sha256:1d339b004f764d6cd0f06e690f6dd748df3d62e6fe1a692d6a5500ac2c5b75a5"
             ],
             "index": "pypi",
-            "version": "==0.3.10"
+            "version": "==0.3.12"
         },
         "pytest-cov": {
             "hashes": [
-                "sha256:cc6742d8bac45070217169f5f72ceee1e0e55b0221f54bcf24845972d3a47f2b",
-                "sha256:cdbdef4f870408ebdbfeb44e63e07eb18bb4619fae852f6e760645fa36172626"
+                "sha256:359952d9d39b9f822d9d29324483e7ba04a3a17dd7d05aa6beb7ea01e359e5f7",
+                "sha256:bdb9fdb0b85a7cc825269a4c56b48ccaa5c7e365054b6038772c32ddcdc969da"
             ],
             "index": "pypi",
-            "version": "==2.8.1"
+            "version": "==2.11.1"
         },
         "pytest-flake8": {
             "hashes": [
-                "sha256:1b82bb58c88eb1db40524018d3fcfd0424575029703b4e2d8e3ee873f2b17027",
-                "sha256:2e91578ecd9b200066f99c1e1de0f510fbb85bcf43712d46ea29fe47607cc234"
+                "sha256:c28cf23e7d359753c896745fd4ba859495d02e16c84bac36caa8b1eec58f5bc1",
+                "sha256:f0259761a903563f33d6f099914afef339c085085e643bee8343eb323b32dd6b"
             ],
             "index": "pypi",
-            "version": "==1.0.6"
+            "version": "==1.0.7"
         },
         "pytest-mypy": {
             "hashes": [
-                "sha256:bb70bb64768a87dbbee250eee7932c84d1e8ccf68c4ce0651304b9598d072d6b",
-                "sha256:f766b229b2760f99524f2c40c24e3288d4853334e560ab5b59a4ebffb2d4cb1d"
+                "sha256:1fa55723a4bf1d054fcba1c3bd694215a2a65cc95ab10164f5808afd893f3b11",
+                "sha256:6e68e8eb7ceeb7d1c83a1590912f784879f037b51adfb9c17b95c6b2fc57466b"
             ],
             "index": "pypi",
-            "version": "==0.6.1"
+            "version": "==0.8.1"
         },
         "pytz": {
             "hashes": [
-                "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",
-                "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"
+                "sha256:16962c5fb8db4a8f63a26646d8886e9d769b6c511543557bc84e9569fb9a9cb4",
+                "sha256:180befebb1927b16f6b57101720075a984c019ac16b1b7575673bea42c6c3da5"
             ],
-            "version": "==2019.3"
+            "version": "==2020.5"
         },
         "regex": {
             "hashes": [
-                "sha256:01b2d70cbaed11f72e57c1cfbaca71b02e3b98f739ce33f5f26f71859ad90431",
-                "sha256:046e83a8b160aff37e7034139a336b660b01dbfe58706f9d73f5cdc6b3460242",
-                "sha256:113309e819634f499d0006f6200700c8209a2a8bf6bd1bdc863a4d9d6776a5d1",
-                "sha256:200539b5124bc4721247a823a47d116a7a23e62cc6695744e3eb5454a8888e6d",
-                "sha256:25f4ce26b68425b80a233ce7b6218743c71cf7297dbe02feab1d711a2bf90045",
-                "sha256:269f0c5ff23639316b29f31df199f401e4cb87529eafff0c76828071635d417b",
-                "sha256:5de40649d4f88a15c9489ed37f88f053c15400257eeb18425ac7ed0a4e119400",
-                "sha256:7f78f963e62a61e294adb6ff5db901b629ef78cb2a1cfce3cf4eeba80c1c67aa",
-                "sha256:82469a0c1330a4beb3d42568f82dffa32226ced006e0b063719468dcd40ffdf0",
-                "sha256:8c2b7fa4d72781577ac45ab658da44c7518e6d96e2a50d04ecb0fd8f28b21d69",
-                "sha256:974535648f31c2b712a6b2595969f8ab370834080e00ab24e5dbb9d19b8bfb74",
-                "sha256:99272d6b6a68c7ae4391908fc15f6b8c9a6c345a46b632d7fdb7ef6c883a2bbb",
-                "sha256:9b64a4cc825ec4df262050c17e18f60252cdd94742b4ba1286bcfe481f1c0f26",
-                "sha256:9e9624440d754733eddbcd4614378c18713d2d9d0dc647cf9c72f64e39671be5",
-                "sha256:9ff16d994309b26a1cdf666a6309c1ef51ad4f72f99d3392bcd7b7139577a1f2",
-                "sha256:b33ebcd0222c1d77e61dbcd04a9fd139359bded86803063d3d2d197b796c63ce",
-                "sha256:bba52d72e16a554d1894a0cc74041da50eea99a8483e591a9edf1025a66843ab",
-                "sha256:bed7986547ce54d230fd8721aba6fd19459cdc6d315497b98686d0416efaff4e",
-                "sha256:c7f58a0e0e13fb44623b65b01052dae8e820ed9b8b654bb6296bc9c41f571b70",
-                "sha256:d58a4fa7910102500722defbde6e2816b0372a4fcc85c7e239323767c74f5cbc",
-                "sha256:f1ac2dc65105a53c1c2d72b1d3e98c2464a133b4067a51a3d2477b28449709a0"
-            ],
-            "version": "==2020.2.20"
+                "sha256:02951b7dacb123d8ea6da44fe45ddd084aa6777d4b2454fa0da61d569c6fa538",
+                "sha256:0d08e71e70c0237883d0bef12cad5145b84c3705e9c6a588b2a9c7080e5af2a4",
+                "sha256:1862a9d9194fae76a7aaf0150d5f2a8ec1da89e8b55890b1786b8f88a0f619dc",
+                "sha256:1ab79fcb02b930de09c76d024d279686ec5d532eb814fd0ed1e0051eb8bd2daa",
+                "sha256:1fa7ee9c2a0e30405e21031d07d7ba8617bc590d391adfc2b7f1e8b99f46f444",
+                "sha256:262c6825b309e6485ec2493ffc7e62a13cf13fb2a8b6d212f72bd53ad34118f1",
+                "sha256:2a11a3e90bd9901d70a5b31d7dd85114755a581a5da3fc996abfefa48aee78af",
+                "sha256:2c99e97d388cd0a8d30f7c514d67887d8021541b875baf09791a3baad48bb4f8",
+                "sha256:3128e30d83f2e70b0bed9b2a34e92707d0877e460b402faca908c6667092ada9",
+                "sha256:38c8fd190db64f513fe4e1baa59fed086ae71fa45083b6936b52d34df8f86a88",
+                "sha256:3bddc701bdd1efa0d5264d2649588cbfda549b2899dc8d50417e47a82e1387ba",
+                "sha256:4902e6aa086cbb224241adbc2f06235927d5cdacffb2425c73e6570e8d862364",
+                "sha256:49cae022fa13f09be91b2c880e58e14b6da5d10639ed45ca69b85faf039f7a4e",
+                "sha256:56e01daca75eae420bce184edd8bb341c8eebb19dd3bce7266332258f9fb9dd7",
+                "sha256:5862975b45d451b6db51c2e654990c1820523a5b07100fc6903e9c86575202a0",
+                "sha256:6a8ce43923c518c24a2579fda49f093f1397dad5d18346211e46f134fc624e31",
+                "sha256:6c54ce4b5d61a7129bad5c5dc279e222afd00e721bf92f9ef09e4fae28755683",
+                "sha256:6e4b08c6f8daca7d8f07c8d24e4331ae7953333dbd09c648ed6ebd24db5a10ee",
+                "sha256:717881211f46de3ab130b58ec0908267961fadc06e44f974466d1887f865bd5b",
+                "sha256:749078d1eb89484db5f34b4012092ad14b327944ee7f1c4f74d6279a6e4d1884",
+                "sha256:7913bd25f4ab274ba37bc97ad0e21c31004224ccb02765ad984eef43e04acc6c",
+                "sha256:7a25fcbeae08f96a754b45bdc050e1fb94b95cab046bf56b016c25e9ab127b3e",
+                "sha256:83d6b356e116ca119db8e7c6fc2983289d87b27b3fac238cfe5dca529d884562",
+                "sha256:8b882a78c320478b12ff024e81dc7d43c1462aa4a3341c754ee65d857a521f85",
+                "sha256:8f6a2229e8ad946e36815f2a03386bb8353d4bde368fdf8ca5f0cb97264d3b5c",
+                "sha256:9801c4c1d9ae6a70aeb2128e5b4b68c45d4f0af0d1535500884d644fa9b768c6",
+                "sha256:a15f64ae3a027b64496a71ab1f722355e570c3fac5ba2801cafce846bf5af01d",
+                "sha256:a3d748383762e56337c39ab35c6ed4deb88df5326f97a38946ddd19028ecce6b",
+                "sha256:a63f1a07932c9686d2d416fb295ec2c01ab246e89b4d58e5fa468089cab44b70",
+                "sha256:b2b1a5ddae3677d89b686e5c625fc5547c6e492bd755b520de5332773a8af06b",
+                "sha256:b2f4007bff007c96a173e24dcda236e5e83bde4358a557f9ccf5e014439eae4b",
+                "sha256:baf378ba6151f6e272824b86a774326f692bc2ef4cc5ce8d5bc76e38c813a55f",
+                "sha256:bafb01b4688833e099d79e7efd23f99172f501a15c44f21ea2118681473fdba0",
+                "sha256:bba349276b126947b014e50ab3316c027cac1495992f10e5682dc677b3dfa0c5",
+                "sha256:c084582d4215593f2f1d28b65d2a2f3aceff8342aa85afd7be23a9cad74a0de5",
+                "sha256:d1ebb090a426db66dd80df8ca85adc4abfcbad8a7c2e9a5ec7513ede522e0a8f",
+                "sha256:d2d8ce12b7c12c87e41123997ebaf1a5767a5be3ec545f64675388970f415e2e",
+                "sha256:e32f5f3d1b1c663af7f9c4c1e72e6ffe9a78c03a31e149259f531e0fed826512",
+                "sha256:e3faaf10a0d1e8e23a9b51d1900b72e1635c2d5b0e1bea1c18022486a8e2e52d",
+                "sha256:f7d29a6fc4760300f86ae329e3b6ca28ea9c20823df123a2ea8693e967b29917",
+                "sha256:f8f295db00ef5f8bae530fc39af0b40486ca6068733fb860b42115052206466f"
+            ],
+            "version": "==2020.11.13"
         },
         "requests": {
             "hashes": [
-                "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
-                "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
-            ],
-            "version": "==2.23.0"
-        },
-        "six": {
-            "hashes": [
-                "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
-                "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
+                "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804",
+                "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"
             ],
-            "version": "==1.14.0"
+            "version": "==2.25.1"
         },
         "snowballstemmer": {
             "hashes": [
-                "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0",
-                "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"
+                "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2",
+                "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"
             ],
-            "version": "==2.0.0"
+            "version": "==2.1.0"
         },
         "sphinx": {
             "hashes": [
-                "sha256:50972d83b78990fd61d0d3fe8620814cae53db29443e92c13661bc43dff46ec8",
-                "sha256:8411878f4768ec2a8896b844d68070204f9354a831b37937989c2e559d29dffc"
+                "sha256:41cad293f954f7d37f803d97eb184158cfd90f51195131e94875bc07cd08b93c",
+                "sha256:c314c857e7cd47c856d2c5adff514ac2e6495f8b8e0f886a8a37e9305dfea0d8"
             ],
-            "version": "==3.0.1"
+            "version": "==3.4.3"
+        },
+        "sphinx-multiversion": {
+            "editable": true,
+            "git": "https://github.com/dls-controls/sphinx-multiversion.git",
+            "ref": "3e72beb7f8f0a76b53722fb2eb3daeed3d2a3d31"
         },
         "sphinx-rtd-theme": {
             "hashes": [
-                "sha256:00cf895504a7895ee433807c62094cf1e95f065843bf3acd17037c3e9a2becd4",
-                "sha256:728607e34d60456d736cc7991fd236afb828b21b82f956c5ea75f94c8414040a"
+                "sha256:eda689eda0c7301a80cf122dad28b1861e5605cbf455558f3775e1e8200e83a5",
+                "sha256:fa6bebd5ab9a73da8e102509a86f3fcc36dec04a0b52ea80e5a033b2aba00113"
             ],
             "index": "pypi",
-            "version": "==0.4.3"
+            "version": "==0.5.1"
         },
         "sphinxcontrib-applehelp": {
             "hashes": [
@@ -556,72 +604,74 @@
         },
         "testfixtures": {
             "hashes": [
-                "sha256:799144b3cbef7b072452d9c36cbd024fef415ab42924b96aad49dfd9c763de66",
-                "sha256:cdfc3d73cb6d3d4dc3c67af84d912e86bf117d30ae25f02fe823382ef99383d2"
+                "sha256:5ec3a0dd6f71cc4c304fbc024a10cc293d3e0b852c868014b9f233203e149bda",
+                "sha256:9ed31e83f59619e2fa17df053b241e16e0608f4580f7b5a9333a0c9bdcc99137"
             ],
-            "version": "==6.14.0"
+            "version": "==6.17.1"
         },
         "toml": {
             "hashes": [
-                "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
-                "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
+                "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
+                "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
             ],
-            "version": "==0.10.0"
+            "version": "==0.10.2"
         },
         "typed-ast": {
             "hashes": [
-                "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
-                "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
-                "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
-                "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
-                "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
-                "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
-                "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
-                "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
-                "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
-                "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
-                "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
-                "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
-                "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
-                "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
-                "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
-                "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
-                "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
-                "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
-                "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
-                "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
-                "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
-            ],
-            "version": "==1.4.1"
+                "sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1",
+                "sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d",
+                "sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6",
+                "sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd",
+                "sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37",
+                "sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151",
+                "sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07",
+                "sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440",
+                "sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70",
+                "sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496",
+                "sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea",
+                "sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400",
+                "sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc",
+                "sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606",
+                "sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc",
+                "sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581",
+                "sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412",
+                "sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a",
+                "sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2",
+                "sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787",
+                "sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f",
+                "sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937",
+                "sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64",
+                "sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487",
+                "sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b",
+                "sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41",
+                "sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a",
+                "sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3",
+                "sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166",
+                "sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10"
+            ],
+            "version": "==1.4.2"
         },
         "typing-extensions": {
             "hashes": [
-                "sha256:091ecc894d5e908ac75209f10d5b4f118fbdb2eb1ede6a63544054bb1edb41f2",
-                "sha256:910f4656f54de5993ad9304959ce9bb903f90aadc7c67a0bef07e678014e892d",
-                "sha256:cf8b63fedea4d89bab840ecbb93e75578af28f76f66c35889bd7065f5af88575"
+                "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918",
+                "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c",
+                "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"
             ],
-            "version": "==3.7.4.1"
+            "version": "==3.7.4.3"
         },
         "urllib3": {
             "hashes": [
-                "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527",
-                "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"
-            ],
-            "version": "==1.25.9"
-        },
-        "wcwidth": {
-            "hashes": [
-                "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1",
-                "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"
+                "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df",
+                "sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"
             ],
-            "version": "==0.1.9"
+            "version": "==1.26.4"
         },
         "zipp": {
             "hashes": [
-                "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b",
-                "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"
+                "sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108",
+                "sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb"
             ],
-            "version": "==3.1.0"
+            "version": "==3.4.0"
         }
     }
 }
diff --git a/README.rst b/README.rst
index 3c82fe2..dafc832 100644
--- a/README.rst
+++ b/README.rst
@@ -1,11 +1,18 @@
 aioca
 =====
 
-|build_status| |coverage| |pypi_version| |readthedocs|
+|code_ci| |docs_ci| |coverage| |pypi_version| |license|
 
 aioca is an asynchronous Channel Access client for asyncio and Python using
-libca via ctypes. It exposes a high level interface similar to the commandline
-tools::
+libca via ctypes.
+
+============== ==============================================================
+PyPI           ``pip install aioca``
+Source code    https://github.com/dls-controls/aioca
+Documentation  https://dls-controls.github.io/aioca
+============== ==============================================================
+
+It exposes a high level interface similar to the commandline tools::
 
     caget(pvs, ...)
         Returns a single snapshot of the current value of each PV.
@@ -20,59 +27,28 @@ tools::
         Optionally can be used to establish PV connection before using the PV.
 
 
-Documentation
--------------
-
-Full documentation is available at http://aioca.readthedocs.io
-
-Source Code
------------
-
-Available from https://github.com/dls-controls/aioca
-
-Installation
-------------
-
-To install the latest release, type::
-
-    pip install aioca
+.. |code_ci| image:: https://github.com/dls-controls/aioca/workflows/Code%20CI/badge.svg?branch=master
+    :target: https://github.com/dls-controls/aioca/actions?query=workflow%3A%22Code+CI%22
+    :alt: Code CI
 
-Changelog
----------
+.. |docs_ci| image:: https://github.com/dls-controls/aioca/workflows/Docs%20CI/badge.svg?branch=master
+    :target: https://github.com/dls-controls/aioca/actions?query=workflow%3A%22Docs+CI%22
+    :alt: Docs CI
 
-See CHANGELOG_
+.. |coverage| image:: https://codecov.io/gh/dls-controls/aioca/branch/master/graph/badge.svg
+    :target: https://codecov.io/gh/dls-controls/aioca
+    :alt: Test Coverage
 
-Contributing
-------------
-
-See CONTRIBUTING_
-
-License
--------
-
-APACHE License. (see LICENSE_)
-
-.. |build_status| image:: https://travis-ci.com/dls-controls/aioca.svg?branch=master
-    :target: https://travis-ci.com/dls-controls/aioca
-    :alt: Build Status
-
-.. |coverage| image:: https://coveralls.io/repos/github/dls-controls/aioca/badge.svg?branch=master
-    :target: https://coveralls.io/github/dls-controls/aioca?branch=master
-    :alt: Test coverage
-
-.. |pypi_version| image:: https://badge.fury.io/py/aioca.svg
-    :target: https://badge.fury.io/py/aioca
+.. |pypi_version| image:: https://badge.fury.io/py/dls-controls.svg
+    :target: https://badge.fury.io/py/dls-controls
     :alt: Latest PyPI version
 
-.. |readthedocs| image:: https://readthedocs.org/projects/aioca/badge/?version=latest
-    :target: http://aioca.readthedocs.io
-    :alt: Documentation
-
-.. _CHANGELOG:
-    https://github.com/dls-controls/aioca/blob/master/CHANGELOG.rst
+.. |license| image:: https://img.shields.io/badge/License-Apache%202.0-blue.svg
+    :target: https://opensource.org/licenses/Apache-2.0
+    :alt: Apache License
 
-.. _CONTRIBUTING:
-    https://github.com/dls-controls/aioca/blob/master/CONTRIBUTING.rst
+..
+    These definitions are used when viewing README.rst and will be replaced
+    when included in index.rst
 
-.. _LICENSE:
-    https://github.com/dls-controls/aioca/blob/master/LICENSE
\ No newline at end of file
+See https://dls-controls.github.io/aioca for more detailed documentation.
\ No newline at end of file
diff --git a/aioca/_catools.py b/aioca/_catools.py
index 3a06800..372b16d 100644
--- a/aioca/_catools.py
+++ b/aioca/_catools.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import asyncio
 import atexit
 import collections
@@ -28,9 +30,9 @@
 from .types import AugmentedValue, Count, Datatype, Dbe, Format, Timeout
 
 T = TypeVar("T")
-PVS = Union[List[str], Tuple[str, ...]]
+PVs = Union[List[str], Tuple[str, ...]]
 
-DEFAULT_TIMEOUT = 5
+DEFAULT_TIMEOUT = 5.0
 
 
 class ValueEvent(Generic[T]):
@@ -85,7 +87,6 @@ def maybe_throw(async_function):
     transformed into an ordinary CANothing value!"""
 
     @functools.singledispatch
-    @functools.wraps(async_function)
     async def throw_wrapper(
         pv, *args, timeout: Timeout = DEFAULT_TIMEOUT, throw=True, **kwargs
     ):
@@ -105,7 +106,24 @@ async def throw_wrapper(
             except cadef.Disconnected:
                 return CANothing(pv, cadef.ECA_DISCONN)
 
-    return throw_wrapper
+    # The singledispatch decorator makes a sync wrapper. We need it to be
+    # async so it works with inspect.iscoroutine, so wrap it again
+    @functools.wraps(async_function)
+    async def call_wrapper(*args, **kwargs):
+        return await throw_wrapper(*args, **kwargs)
+
+    # But keep the register function and register a signature that includes
+    # the extras we added
+    call_wrapper.register = throw_wrapper.register
+    original_sig = inspect.signature(async_function)
+    throw_parameters = inspect.signature(throw_wrapper).parameters
+    parameters = [
+        *original_sig.parameters.values(),
+        throw_parameters["timeout"],
+        throw_parameters["throw"],
+    ]
+    call_wrapper.__signature__ = original_sig.replace(parameters=parameters)
+    return call_wrapper
 
 
 async def ca_timeout(awaitable: Awaitable[T], name: str, timeout: Timeout = None) -> T:
@@ -488,7 +506,7 @@ def camonitor(
 
 @overload
 def camonitor(
-    pv: PVS,
+    pv: PVs,
     callback: Callable[[Any, int], Union[None, Awaitable]],
     events: Dbe = ...,
     datatype: Datatype = ...,
@@ -589,7 +607,7 @@ async def caget(
 
 @overload
 async def caget(
-    pvs: PVS,
+    pvs: PVs,
     datatype: Datatype = ...,
     format: Format = ...,
     count: Count = ...,
@@ -651,7 +669,7 @@ async def caget(pv: str, datatype=None, format=dbr.FORMAT_RAW, count=0):
 
 @caget.register(list)  # type: ignore
 @caget.register(tuple)  # type: ignore
-async def caget_array(pvs: PVS, **kwargs):
+async def caget_array(pvs: PVs, **kwargs):
     # Spawn a separate caget task for each pv: this allows them to complete
     # in parallel which can speed things up considerably.
     coros = [caget(pv, **parallel_timeout(kwargs)) for pv in pvs]
@@ -694,7 +712,7 @@ async def caput(
 
 @overload
 async def caput(
-    pvs: PVS,
+    pvs: PVs,
     values,
     repeat_value: bool = ...,
     datatype: Datatype = ...,
@@ -763,7 +781,7 @@ async def caput(pv: str, value, datatype=None, wait=False):
 
 @caput.register(list)  # type: ignore
 @caput.register(tuple)  # type: ignore
-async def caput_array(pvs: PVS, values, repeat_value=False, **kwargs):
+async def caput_array(pvs: PVs, values, repeat_value=False, **kwargs):
     # Bring the arrays of pvs and values into alignment.
     if repeat_value or isinstance(values, str):
         # If repeat_value is requested or the value is a string then we treat
@@ -856,7 +874,7 @@ async def connect(
 
 @overload
 async def connect(
-    pv: PVS, wait: bool = ..., timeout: Timeout = ..., throw: bool = ...
+    pv: PVs, wait: bool = ..., timeout: Timeout = ..., throw: bool = ...
 ) -> List[CANothing]:
     ...  # pragma: no cover
 
@@ -889,7 +907,7 @@ async def connect(pv: str, wait=True):
 
 @connect.register(list)  # type: ignore
 @connect.register(tuple)  # type: ignore
-async def connect_array(pvs: PVS, wait=True, **kwargs):
+async def connect_array(pvs: PVs, wait=True, **kwargs):
     coros = [connect(pv, **parallel_timeout(kwargs)) for pv in pvs]
     results = await in_parallel(coros, kwargs)
     return results
@@ -904,7 +922,7 @@ async def cainfo(
 
 @overload
 async def cainfo(
-    pv: PVS, wait: bool = ..., timeout: Timeout = ..., throw: bool = ...
+    pv: PVs, wait: bool = ..., timeout: Timeout = ..., throw: bool = ...
 ) -> List[CAInfo]:
     ...  # pragma: no cover
 
@@ -923,7 +941,7 @@ async def cainfo(pv: str, wait=True):
 
 @cainfo.register(tuple)  # type: ignore
 @cainfo.register(list)  # type: ignore
-async def cainfo_array(pvs: PVS, wait=True, **kwargs):
+async def cainfo_array(pvs: PVs, wait=True, **kwargs):
     coros = [cainfo(pv, **parallel_timeout(kwargs)) for pv in pvs]
     results = await in_parallel(coros, kwargs)
     return results
diff --git a/aioca/types.py b/aioca/types.py
index ca8bd0e..383bb3a 100644
--- a/aioca/types.py
+++ b/aioca/types.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 from datetime import datetime
 from typing import List, Sized, Tuple, Type, Union
 
@@ -61,12 +63,14 @@
 
 #: The format of the requested data can be one of the following
 #:
-#: - None (the default), in this case the "native" datatype provided
-#:   by the channel will be returned
-#: - A `Dbr` value
-#: - A python type compatible with any of the above values, such as
-#:   int, float or str
-#: - Any numpy dtype compatible with any of the above values
+#: ==================== ================================================
+#: None (the default)   In this case the "native" datatype provided
+#:                      by the channel will be returned
+#: A `Dbr` value        To request this type from the IOC
+#: A python type        Compatible with any of the above values,
+#:                      such as int, float or str
+#: A numpy dtype        Compatible with any of the above values
+#: ==================== ================================================
 Datatype = Union[None, Dbr, Type]
 
 #: How much auxilliary information will be returned with the retrieved data.
@@ -88,7 +92,7 @@
 #: -1       The full data length
 #: +ve int  A maximum of this number of elements
 #: ======== ============================================================
-Count = Union[Literal[0], int]
+Count = Union[Literal[0, -1], int]
 
 
 class AugmentedValue(Protocol, Sized):
diff --git a/docs/conf.py b/docs/conf.py
index d9e234a..58e4575 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -25,14 +25,15 @@
 author = "Tom Cobb"
 
 
-# The short X.Y version.
-version = aioca.__version__.split("+")[0]
 # The full version, including alpha/beta/rc tags.
 release = aioca.__version__
 
-if os.environ.get("READTHEDOCS") == "True":
-    # Readthedocs modifies conf.py, so will appear dirty when it isn't
-    release = release.split("+0")[0].replace(".dirty", "")
+# The short X.Y version.
+if "+" in release:
+    # Not on a tag
+    version = "master"
+else:
+    version = release
 
 extensions = [
     # Use this for generating API docs
@@ -53,14 +54,6 @@
 # be found.
 nitpicky = True
 
-# Don’t use a saved environment (the structure caching all cross-references),
-# but rebuild it completely.
-fresh_env = True
-
-# Turn warnings into errors. This means that the build stops at the first
-# warning and sphinx-build exits with exit status 1.
-warning_is_error = True
-
 # Both the class’ and the __init__ method’s docstring are concatenated and
 # inserted into the main body of the autoclass directive
 autoclass_content = "both"
@@ -68,6 +61,23 @@
 # Order the members by the order they appear in the source code
 autodoc_member_order = "bysource"
 
+# A dictionary for users defined type aliases that maps a type name to the
+# full-qualified object name. It is used to keep type aliases not evaluated in
+# the document. Defaults to empty ({}).
+# TODO: drop when https://github.com/sphinx-doc/sphinx/issues/8934 works
+autodoc_type_aliases = dict(
+    Count="aioca.types.Count",
+    Datatype="aioca.types.Datatype",
+    Dbe="aioca.types.Dbe",
+    Dbr="aioca.types.Dbr",
+    Format="aioca.types.Format",
+    Timeout="aioca.types.Timeout",
+    # Explicitly tell sphinx to use the right namespace for these, otherwise
+    # we get aioca._catools.CANothing that it can't find
+    CANothing="aioca.CANothing",
+    CAInfo="aioca.CAInfo",
+    Subscription="aioca.Subscription",
+)
 # Output graphviz directive produced images in a scalable format
 graphviz_output_format = "svg"
 
@@ -126,3 +136,11 @@
 
 # Override the colour in a custom css file
 html_css_files = ["theme_overrides.css"]
+
+# sphinx-multiversion config
+smv_rebuild_tags = False
+smv_tag_whitelist = r"^\d+\.\d+.*$"  # only document tags with form 0.9*
+smv_branch_whitelist = r"^master$"  # only branch to document is master
+smv_outputdir_format = "{ref.name}"
+smv_prefer_remote_refs = True
+smv_remote_whitelist = "origin|github"
diff --git a/docs/requirements.txt b/docs/requirements.txt
deleted file mode 100644
index c9173a1..0000000
--- a/docs/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-epicscorelibs>=7.0.3.99.4.0
-typing_extensions
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..b0471b7
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["setuptools", "wheel"]
+build-backend = "setuptools.build_meta:__legacy__"
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
index 3d8a90e..09e1fde 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -6,12 +6,14 @@ author = Tom Cobb
 author_email = tom.cobb@diamond.ac.uk
 license = Apache License 2.0
 long_description = file: README.rst
+long_description_content_type = text/x-rst
 classifiers =
-    Development Status :: 4 - Beta
+    Development Status :: 5 - Production/Stable
     License :: OSI Approved :: Apache Software License
     Programming Language :: Python :: 3 :: Only
     Programming Language :: Python :: 3.7
     Programming Language :: Python :: 3.8
+    Programming Language :: Python :: 3.9
 
 [options]
 # Locate packages automatically
@@ -21,10 +23,6 @@ install_requires =
      epicscorelibs >= 7.0.3.99.4.0
      typing_extensions
 
-# If you want to include data files in packages,
-# set following to True and include a MANIFEST.in file.
-include_package_data = False
-
 [options.packages.find]
 # Don't include our tests directory in the distribution
 exclude = tests
@@ -34,12 +32,8 @@ exclude = tests
 ignore_missing_imports = True
 
 [isort]
-# https://black.readthedocs.io/en/stable/the_black_code_style.html?highlight=isort#how-black-wraps-lines
-multi_line_output=3
-include_trailing_comma=True
-force_grid_wrap=0
-use_parentheses=True
-line_length=88
+profile=black
+float_to_top=true
 skip=setup.py,conf.py
 
 [flake8]
@@ -51,4 +45,9 @@ extend-ignore =
 
 [tool:pytest]
 # Run pytest with all our checkers, and don't spam us with massive tracebacks on error
-addopts = --tb=native -vv --flake8 --black --mypy
+# Turn off unraisable exceptions as we want to check for them in test_closing_event_loop()
+addopts = --tb=native -vv --flake8 --black --mypy -p no:unraisableexception
+
+[coverage:run]
+# This is covered in the versiongit test suite so exclude it here
+omit = */_version_git.py


Test patch:
diff --git a/tests/test_aioca.py b/tests/test_aioca.py
index 39583ec..6b46fca 100644
--- a/tests/test_aioca.py
+++ b/tests/test_aioca.py
@@ -223,7 +223,7 @@ async def test_caget_non_existent() -> None:
     assert f"{NE}: User specified timeout on IO operation expired" == str(cm.value)
     assert False is bool(cm.value)
     with pytest.raises(TypeError):
-        for _ in cm.value:
+        for _ in cm.value:  # type: ignore
             pass