Repository: lewoudar/scalpel (language: python)

Issue:
Add support for asyncio
I don't like asyncio design to be honest but the work made by the author of [anyio](https://anyio.readthedocs.io/en/stable/) is awesome.
It brings the trio api to asyncio and therefore made it easy to support it. I will work on it soon.


Discussion / hints:

Fix patch:
diff --git a/.github/scripts/chromedriver.sh b/.github/scripts/chromedriver.sh
deleted file mode 100644
index 51983f0..0000000
--- a/.github/scripts/chromedriver.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-# the script is inspired by this gist https://gist.github.com/ziadoz/3e8ab7e944d02fe872c3454d17af31a5
-
-set -ex -o pipefail
-
-echo "Install chromedriver"
-
-CHROME_DRIVER_VERSION=$(curl -sS https://chromedriver.storage.googleapis.com/LATEST_RELEASE)
-
-wget -N https://chromedriver.storage.googleapis.com/"$CHROME_DRIVER_VERSION"/chromedriver_linux64.zip -P ~/
-
-unzip ~/chromedriver_linux64.zip -d ~/
-
-rm ~/chromedriver_linux64.zip
-
-sudo mv -f ~/chromedriver /usr/local/bin/chromedriver
-
-sudo chown root:root /usr/local/bin/chromedriver
-
-sudo chmod 0755 /usr/local/bin/chromedriver
diff --git a/.github/scripts/geckodriver.sh b/.github/scripts/geckodriver.sh
deleted file mode 100644
index dde52aa..0000000
--- a/.github/scripts/geckodriver.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-# the script is inspired by this article https://dev.to/erikwhiting88/install-browsers-and-webdrivers-in-travisci-n76
-
-set -ex -o pipefail
-
-echo "Install geckodriver"
-
-wget -N https://github.com/mozilla/geckodriver/releases/download/v0.27.0/geckodriver-v0.27.0-linux64.tar.gz -P ~/
-
-tar -xzf ~/geckodriver-v0.27.0-linux64.tar.gz -C ~/
-
-rm ~/geckodriver-v0.27.0-linux64.tar.gz
-
-sudo mv -f ~/geckodriver /usr/local/bin/geckodriver
-
-sudo chmod 0755 /usr/local/bin/geckodriver
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index d2831de..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-dist: xenial
-language: python
-python: [ pypy3 ]
-
-addons:
-  chrome: stable
-  firefox: latest
-
-before_install:
-  - bash .github/scripts/chromedriver.sh
-  - bash .github/scripts/geckodriver.sh
-
-install: pip install -U pip setuptools nox
-
-script: nox -s tests-pypy3
diff --git a/CHANGELOG.md b/CHANGELOG.md
index aa048ab..ed81055 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,18 +2,22 @@
 
 The changelog format is based on a subset of [Keep a changelog](https://keepachangelog.com/en/1.0.0/).
 
-## Version 0.1.1
+## [Unreleased]
 
-Released on 2020-11-02
+## Version 0.1.2 - 2021-XX-XX
+
+### Changed
+
+- Changed trio backend to an anyio backend. This adds support to asyncio in addition to trio.
+
+## [0.1.1] - 2020-11-02
 
 ### Fixed
 
 - Package deployment via nox
 - Package installation for the gevent backend
 
-## Version 0.1.0
-
-Released on 2020-11-02
+## [0.1.0] - 2020-11-02
 
 ### Added
 
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 861c682..3408c47 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -10,10 +10,11 @@ To submit a bug report, please use the [issue tracker](https://github.com/lewoud
 
 Before trying to submit an issue, make sure that there is not already a similar one reported.
 
-Your message should contains as much information as possible such as:
-- the environment in which you worked (OS name and version, python version, etc..)
+Your message should contain as much information as possible such as:
+
+- the environment in which you worked (OS name and version, python version, etc...)
 - Guidance on how to reproduce the issue. For example a small piece of code that can be run immediately.
-- Tell me **what you mean by failure** i.e what are you expecting to happen.
+- Tell me **what you mean by failure** i.e. what are you expecting to happen.
 
 # Fix a bug
 
@@ -22,7 +23,8 @@ correct it. Look at [code contribution](#code-contribution) section before submi
 
 ## Submit feedback
 
-To submit feedback, again use the [issue tracker](https://github.com/lewoudar/configuror/issues).
+To submit feedback, use the [discussions](https://github.com/lewoudar/scalpel/discussions) forum. Please **do not use
+the issue tracker**, I will just close it.
 
 If you want to propose a new feature:
 - explain in detail how it would work.
@@ -33,14 +35,15 @@ If you want to propose a new feature:
 
 The documentation is never a simple part to write, if you feel that it can be improved, feel free to propose a pull
 request. Just a few things to be aware of:
+
 - The documentation is built with [mkdocs](https://www.mkdocs.org/) using the markdown syntax.
 - Try to follow the style of the documentation, for example do not have lines longer than 120 characters, use
-single-quotes strings ('hello' instead of "hello") when presenting python code.
-- Look at the [code contribution](#code-contribution) section for how to setup the project and commit convention.
+  single-quotes strings ('hello' instead of "hello") when presenting python code.
+- Look at the [code contribution](#code-contribution) section for how to set up the project and commit convention.
 
 ## Code contribution
 
-Ready to contribute? Here is how to setup the project for local development.
+Ready to contribute? Here is how to set up the project for local development.
 1. Fork the configuror repo on Github.
 
 2. Clone your fork locally. If you don't know how to proceed, 
@@ -62,16 +65,15 @@ Ready to contribute? Here is how to setup the project for local development.
     nox -s lint tests
     ```
 
-6. Commit your changes and push your branch to GitHub.
-    For the commit message, you should use the convention described [here](https://medium.com/@menuka/writing-meaningful-git-commit-messages-a62756b65c81).
-    It is the convention developed by the angular project. There is  just one notable difference I'm adding.
-    The verb must be conjugated **in the past tense** because I believe we are talking about a done action and not an
-    action to be performed.
-    Also for the scope, there is no particular set of scopes, so feel free to add what you thinks suits well your
-    changes. If you don't have one in mind, don't put anything.
+6. Commit your changes and push your branch to GitHub. For the commit message, you should use the convention
+   described [here](https://medium.com/@menuka/writing-meaningful-git-commit-messages-a62756b65c81). It is the
+   convention developed by the angular project. There is just one notable difference I'm adding. The verb must be
+   conjugated **in the past tense** because I believe we are talking about a done action and not an action to be
+   performed. Also, for the scope, there is no particular set of scopes, so feel free to add what you think suits well
+   your changes. If you don't have one in mind, don't put anything.
 
 7. Before submitting the pull request, you should verify that you include tests. There is also a code coverage
-   configured with the project. You can check the pull request status to know if your tests cover all the code you wrote.
-   If your pull request add functionality, please update the documentation.
+   configured with the project. You can check the pull request status to know if your tests cover all the code you
+   wrote. If your pull request add functionality, please update the documentation.
  
 8. Submit your pull request through the GitHub website.
\ No newline at end of file
diff --git a/README.md b/README.md
index 7c2a488..4a2186f 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # Pyscalpel
 
 [![Pypi version](https://img.shields.io/pypi/v/pyscalpel.svg)](https://pypi.org/project/pyscalpel/)
-![](https://github.com/lewoudar/actions-tutorial/workflows/CI/badge.svg)
+![](https://github.com/lewoudar/scalpel/workflows/CI/badge.svg)
 [![Coverage Status](https://codecov.io/gh/lewoudar/scalpel/branch/master/graphs/badge.svg?branch=master)](https://codecov.io/gh/lewoudar/scalpel)
 [![Documentation Status](https://readthedocs.org/projects/scalpel/badge/?version=latest)](https://scalpel.readthedocs.io/en/latest/?badge=latest)
 [![License Apache 2](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0)
@@ -10,7 +10,7 @@ Your easy-to-use, fast and powerful web scraping library.
 
 ## Why?
 
-I already known [scrapy](https://docs.scrapy.org/en/latest/) which is the reference in python for web scraping. But
+I already knew [scrapy](https://docs.scrapy.org/en/latest/) which is the reference in python for web scraping. But
 two things bothered me.
 - I feel like scrapy cannot integrate into an existing project, you need to treat your web scraping stuff like a project
 on its own.
@@ -25,6 +25,7 @@ on its own.
 ## Installation
  
 ```bash
+pip install pyscalpel  # # to only use the asyncio backend
 pip install pyscalpel[gevent] # to install the gevent backend
 pip install pyscalpel[trio] # to installl the trio backend
 pip install pyscalpel[full] # to install all the backends
@@ -33,6 +34,7 @@ pip install pyscalpel[full] # to install all the backends
 If you know about [poetry](https://python-poetry.org/) you can use it instead of pip.
 
 ```bash
+poetry add pyscalpel  # to only use the asyncio backend
 poetry add pyscalpel[gevent] # to install the gevent backend
 poetry add pyscalpel[trio] # to install the trio backend
 poetry add pyscalpel[full] # to install all the backends
@@ -44,6 +46,8 @@ pyscalpel works starting from **python 3.6**, it relies on robust packages:
 - [selenium](https://pypi.org/project/selenium/): A library for controlling a browser.
 - [gevent](http://www.gevent.org/): An asynchronous framework using the synchronous way. (optional)
 - [trio](https://trio.readthedocs.io/en/stable/): A modern asynchronous framework using `async/await` syntax. (optional)
+- [anyio](https://anyio.readthedocs.io/): An asynchronous networking and concurrency library that works on top of
+either asyncio or trio.
 - [parsel](https://parsel.readthedocs.io/): A library elements in HTML/XML documents.
 - [attrs](https://www.attrs.org/en/stable/): A library helping to write classes without pain.
 - [fake-useragent](https://pypi.org/project/fake-useragent/): A simple library to fake a user agent.
@@ -93,14 +97,14 @@ if __name__ == '__main__':
         print(quote_data)
 ```
 
-with trio
+with anyio
 
 ```python
 from pathlib import Path
 
-import trio
+import anyio
 from scalpel import Configuration
-from scalpel.trionic import StaticResponse, StaticSpider, read_mp
+from scalpel.any_io import StaticResponse, StaticSpider, read_mp
 
 
 async def parse(spider: StaticSpider, response: StaticResponse) -> None:
@@ -127,16 +131,18 @@ async def main():
         print(item)
 
 if __name__ == '__main__':
-    trio.run(main)
+    # by default, this will run the asyncio backend, if you want the trio backend, you must first install the trio 
+    # package and replace the following line with: anyio.run(main, backend='trio').
+    anyio.run(main)
 ```
 
 ## Known limitations
 
-pyscalpel aims to handle SPA (single page application) through the use of selenium. However due to the synchronous nature
-of selenium, it is hard to leverage trio and gevent asynchronous feature. You will notice that the *selenium spider* is
+pyscalpel aims to handle SPA (single page application) through the use of selenium. However, due to the synchronous nature
+of selenium, it is hard to leverage anyio and gevent asynchronous feature. You will notice that the *selenium spider* is
 slower than the *static spider*. For more information look at the documentation.
 
 ## Warning
 
-pyscalpel is a young project so it is expected to have breaking changes in the api without respecting the 
+pyscalpel is a young project, so it is expected to have breaking changes in the api without respecting the 
 [semver](https://semver.org/) principle. It is recommended to pin the version you are using for now.
\ No newline at end of file
diff --git a/docs/faq.md b/docs/faq.md
index 989abfd..7101d12 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -1,47 +1,5 @@
 # FAQ
 
-## How do I run my spider using trio in asyncio code?
-
-Here is a code snippet to show how to run trio code in asyncio.
-
-```python
-import asyncio
-
-import trio
-import sniffio
-from scalpel.trionic import StaticSpider
-
-
-async def parse(*_):
-    pass
-
-
-async def scrape(url):
-    print(f'parsing {url} from {sniffio.current_async_library()}')
-    spider = StaticSpider(urls=[url], parse=parse)
-    await spider.run()
-
-
-def run_trio():
-    trio.run(scrape, 'http://foo.com')
-
-
-async def main():
-    loop = asyncio.get_event_loop()
-    print(f'running main function from {sniffio.current_async_library()}')
-    await loop.run_in_executor(None, run_trio)
-
-
-# if you are using python3.7 upwards, you can replace the following lines with
-# asyncio.run(main())
-loop = asyncio.get_event_loop()
-loop.run_until_complete(main())
-loop.close()
-```
-
-By the way, do you here about [anyio](https://anyio.readthedocs.io/en/stable/)? (yes I do a bit of advertising). It can
-help you write beautiful code as with trio for asyncio :)
-
 ## How do I run my spider using gevent in asyncio code?
 
 **Don't do that!** pyscalpel instructs gevent to monkeypatch various standard library modules and some like socket are
diff --git a/docs/index.md b/docs/index.md
index dee3319..4bb87ce 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -4,7 +4,7 @@ Everything you need to know about pyscalpel.
 
 ## Why pyscalpel?
 
-I already known [scrapy](https://docs.scrapy.org/en/latest/) which is the reference in python for web scraping. But
+I already knew [scrapy](https://docs.scrapy.org/en/latest/) which is the reference in python for web scraping. But
 two things bothered me.
 
 - I feel like scrapy cannot integrate into an existing project, you need to treat your web scraping stuff like a project
@@ -13,17 +13,17 @@ on its own.
 that there are better asynchronous frameworks today. Note that this second point is no longer true anymore as I'm writing
 the documentation because scrapy added support for [asyncio](https://docs.scrapy.org/en/latest/topics/asyncio.html).
  
-After having made these observation I decided to create pyscalpel. And let's be honest, I also want to have my own web
+After having made these observations I decided to create pyscalpel. And let's be honest, I also want to have my own web
 scraping library, and it is fun to write one ;)
  
 ## Features
  
-- Ability to parse documents using `gevent` or `trio` asynchronous frameworks.
+- Ability to parse documents using `gevent`, `asyncio` or `trio` asynchronous frameworks.
 - Ability to parse SPA (Single Page Applications) using `selenium`.
 - Fast serialization for scrapped items with `msgpack`.
 - Ability to follow *robots.txt* rules.
 - Ability to filter or update scraped items.
-- Middleware system to perform some actions regarding to the response (only for static responses).
+- Middleware system to perform some actions regarding the response (only for static responses).
 
 !!! warning
     If you are new to pyscalpel you should read the documentation in the order listed on the left menu.
diff --git a/docs/installation.md b/docs/installation.md
index 49dd8d1..27b24e9 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -4,14 +4,16 @@ To install pyscalpel, you will need to have python and pip installed. For python
 After you can just enter the following command:
 
 ```bash
+pip install pyscalpel # to only use the asyncio backend
 pip install pyscalpel[gevent] # to install the gevent backend
-pip install pyscalpel[trio] # to installl the trio backend
+pip install pyscalpel[trio] # to install the trio backend
 pip install pyscalpel[full] # to install all the backends
 ```
 
 You can also have a look at the [poetry](https://python-poetry.org/docs/) project to manage your dependencies.
 
 ```bash
+poetry add pyscalpel # to only use the asyncio backend
 poetry add pyscalpel[gevent] # to install the gevent backend
 poetry add pyscalpel[trio] # to install the trio backend
 poetry add pyscalpel[full] # to install all the backends
@@ -24,6 +26,8 @@ This project relies on robust packages:
 - [selenium](https://pypi.org/project/selenium/): A library for controlling a browser.
 - [gevent](http://www.gevent.org/): An asynchronous framework using the synchronous way. (optional)
 - [trio](https://trio.readthedocs.io/en/stable/): A modern asynchronous framework using `async/await` syntax. (optional)
+- [anyio](https://anyio.readthedocs.io/): An asynchronous networking and concurrency library that works on top of
+either asyncio or trio.
 - [parsel](https://parsel.readthedocs.io/): A library elements in HTML/XML documents.
 - [attrs](https://www.attrs.org/en/stable/): A library helping to write classes without pain.
 - [fake-useragent](https://pypi.org/project/fake-useragent/): A simple library to fake a user agent.
diff --git a/docs/item-processing.md b/docs/item-processing.md
index 9194f82..7fb711b 100644
--- a/docs/item-processing.md
+++ b/docs/item-processing.md
@@ -23,8 +23,8 @@ config = Configuration(item_processors=[processor_1, processor_2])
 ```
 
 As you will have noticed in the example, item processors can be synchronous or asynchronous. Obviously the asynchronous
-version is only valid if you are dealing with a `trio` spider. If you use an asynchronous function inside a green spider,
-you can be sure your application will crash.
+version is only valid if you are dealing with an `asyncio` or `trio` spider. If you use an asynchronous function inside 
+a green spider, you can be sure your application will crash.
 
 !!! note
     The processors are run in the order there are listed when instantiating configuration. So put the most important
@@ -44,10 +44,10 @@ data = {
 spider.save_item(data)
 ```
 
-So we save an item with three properties `message`,`author` and `tags`. Now lets add a date. And let's say we don't like
+So we save an item with three properties `message`,`author` and `tags`. Now let's add a date and let's say we don't like
 Marylin Monroe, so we want to remove her quotes from the result 😆
 
-I will show an example with gevent, but you should now know how to use trio at this point of the documentation.
+I will show an example with gevent, but you should now know how to use anyio at this point of the documentation.
 
 ```python
 from datetime import datetime
@@ -76,8 +76,8 @@ to mention that if a processor returns `None` the following processors are not c
 
 If you know [msgpack](https://pypi.org/project/msgpack/), you know that it cannot serialize `datetime` objects by
 default. So if you called the `read_mp` function like we did in the static spider guide, it will raise an error.
-So how can we read `datetime` objects? Well, if you look at the pyscalpel [msgpack api](api.md#msgpack) you will noticed
-a `datetime_decoder` which is a helper to deserialize `datetime` objects. Also the [Configuration](api.md#configuration)
+So how can we read `datetime` objects? Well, if you look at the pyscalpel [msgpack api](api.md#msgpack) you will notice
+a `datetime_decoder` which is a helper to deserialize `datetime` objects. Also, the [Configuration](api.md#configuration)
 object has a `msgpack_decoder` attribute which default value is `datetime_decoder`. So here is how you can read
 `datetime` objects.
 
@@ -100,12 +100,12 @@ for data in read_mp('toto.mp', decoder=config.msgpack_decoder):
     print(data)
 ```
 
-With trio:
+With anyio:
 
 ```python
-import trio
+import anyio
 from scalpel import Configuration
-from scalpel.trionic import StaticSpider, read_mp
+from scalpel.any_io import StaticSpider, read_mp
 
 async def parse(spider, response):
     ...
@@ -119,7 +119,7 @@ async def main():
     async for data in read_mp('toto.mp', decoder=config.msgpack_decoder):
         print(data)
 
-trio.run(main)
+anyio.run(main)  # with trio: anyio.run(main, backend='trio')
 ```
 
 If you want to serialize / deserialize other custom objects, you need to implement your logic and set attributes
diff --git a/docs/middleware.md b/docs/middleware.md
index 9415814..87ed150 100644
--- a/docs/middleware.md
+++ b/docs/middleware.md
@@ -58,12 +58,12 @@ spider = StaticSpider(urls=['http://foo.com'], parse=parse, config=config)
 spider.run()
 ```
 
-With trio:
+With anyio:
 
 ```python
-import trio
+import anyio
 from scalpel import Configuration
-from scalpel.trionic import StaticSpider
+from scalpel.any_io import StaticSpider
 
 
 def middleware(fetch):
@@ -107,7 +107,7 @@ async def main():
     spider = StaticSpider(urls=['http://foo.com'], parse=parse, config=config)
     await spider.run()
 
-trio.run(main)
+anyio.run(main)  # with trio: anyio.run(main, backend='trio')
 ```
 
 Output:
diff --git a/docs/requirements.txt b/docs/requirements.txt
index a54f9c1..cc8cb94 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -4,6 +4,7 @@ attrs==19.3.0
 configuror==0.2.0
 trio==0.17.0
 gevent==20.9.0
+anyio
 selenium==3.141.0
 idna>=2.0.0,<3.0.0
 rfc3986==1.4.0
diff --git a/docs/selenium-spider.md b/docs/selenium-spider.md
index 39f0e4f..3549625 100644
--- a/docs/selenium-spider.md
+++ b/docs/selenium-spider.md
@@ -115,7 +115,8 @@ So this is what we can write to scrape all menu information on the website.
 With gevent:
 
 ```python
-from ².green import SeleniumResponse, SeleniumSpider
+from scalpel.green import SeleniumResponse, SeleniumSpider
+
 
 def parse(_, response: SeleniumResponse) -> None:
     for block in response.driver.find_elements_by_xpath('//div[@class="opblock-tag-section"]'):
@@ -144,11 +145,11 @@ spider = SeleniumSpider(urls=['http://httpbin.org/'], parse=parse)
 spider.run()
 ```
 
-With trio:
+With anyio:
 
 ```python
-import trio
-from scalpel.trionic import SeleniumSpider, SeleniumResponse
+import anyio
+from scalpel.any_io import SeleniumSpider, SeleniumResponse
 
 async def parse(_, response: SeleniumResponse) -> None:
     for block in response.driver.find_elements_by_xpath('//div[@class="opblock-tag-section"]'):
@@ -176,7 +177,7 @@ async def main() -> None:
     spider = SeleniumSpider(urls=['http://httpbin.org/'], parse=parse)
     await spider.run()
 
-trio.run(main)
+anyio.run(main)   # with trio: anyio.run(main, backend='trio')
 ```
 
 You will have an output similar to the following:
@@ -251,10 +252,10 @@ def parse(_, response: StaticResponse) -> None:
     response.xpath('//div')
 ```
 
-With trio:
+With anyio:
 
 ```python
-from scalpel.trionic import StaticResponse
+from scalpel.any_io import StaticResponse
 
 async def parse(_, response: StaticResponse) -> None:
     response.xpath('//p')
@@ -264,7 +265,7 @@ async def parse(_, response: StaticResponse) -> None:
     response.xpath('//div')
 ```
 
-Instead you should perform all your code scraping, parsing before running asynchronous operations.
+Instead, you should perform all your code scraping, parsing before running asynchronous operations.
 
 With gevent:
 
@@ -277,10 +278,10 @@ def parse(_, response: StaticResponse) -> None:
     response.follow('/page/2')  # good
 ```
 
-With trio:
+With anyio:
 
 ```python
-from scalpel.trionic import StaticResponse
+from scalpel.any_io import StaticResponse
 
 async def parse(_, response: StaticResponse) -> None:
     response.xpath('//p')
@@ -289,5 +290,5 @@ async def parse(_, response: StaticResponse) -> None:
 ```
 
 Another direct consequence of the bad asynchronous integration of selenium is that if you follow urls you will notice
-that the behaviour is more sequential than concurrent with regard to url handling. Nevertheless the selenium spider
+that the behaviour is more sequential than concurrent with regard to url handling. Nevertheless, the selenium spider
 is still useful (if you respect the previous advice), just slow for now.
\ No newline at end of file
diff --git a/docs/static-spider.md b/docs/static-spider.md
index 033f4ce..38ee58e 100644
--- a/docs/static-spider.md
+++ b/docs/static-spider.md
@@ -41,11 +41,11 @@ static_spider = StaticSpider(urls=['https://quotes.toscrape.com'], parse=parse)
 static_spider.run()
 ```
 
-if you prefer `trio` over `gevent`, this is the equivalent:
+if you prefer `anyio` over `gevent`, this is the equivalent:
 
 ```python
-import trio
-from scalpel.trionic import StaticResponse, StaticSpider
+import anyio
+from scalpel.any_io import StaticResponse, StaticSpider
 
 async def parse(spider: StaticSpider, response: StaticResponse) -> None:
     print('hello spider')
@@ -54,12 +54,20 @@ async def main() -> None:
     spider = StaticSpider(urls=['https://quotes.toscrape.com'], parse=parse)
     await spider.run()
 
-trio.run(main)
+anyio.run(main)
 ```
 
 !!! note
     there is an icon at the top right of the code where you can click to copy and paste into your editor and test it.
 
+!!! note
+    `anyio` by defaults, run the `asyncio` backend. If you want to use the `trio` backend, you **must** first install
+    `trio` and slightly changed the last sentence to `anyio.run(main, backend='trio')`.
+
+!!! note
+    To improve execution speed on asyncio backend, you can leverage the [uvloop](https://uvloop.readthedocs.io/) package.
+    Note that it does not work on **Windows** and performed badly on *Pypy* because it used [cython](https://cython.org/).
+
 If you run this program, you will just see `hello spider` printed in your console. Nothing exciting right now, let's
 change that.
 
@@ -80,11 +88,11 @@ static_spider = StaticSpider(urls=['https://quotes.toscrape.com'], parse=parse)
 static_spider.run()
 ```
 
-with trio:
+with anyio:
 
 ```python
-import trio
-from scalpel.trionic import StaticResponse, StaticSpider
+import anyio
+from scalpel.any_io import StaticResponse, StaticSpider
 
 async def parse(spider: StaticSpider, response: StaticResponse) -> None:
     print(response.css('title').get())
@@ -94,7 +102,7 @@ async def main() -> None:
     spider = StaticSpider(urls=['https://quotes.toscrape.com'], parse=parse)
     await spider.run()
 
-trio.run(main)
+anyio.run(main)
 ```
 
 If you run the program, the content `<title>Quotes to Scrape</title>` will be printed twice. I deliberately wrote the 
@@ -125,11 +133,11 @@ static_spider = StaticSpider(urls=['https://quotes.toscrape.com'], parse=parse)
 static_spider.run()
 ```
 
-With trio:
+With anyio:
 
 ```python
-import trio
-from scalpel.trionic import StaticResponse, StaticSpider
+import anyio
+from scalpel.any_io import StaticResponse, StaticSpider
 
 async def parse(spider: StaticSpider, response: StaticResponse) -> None:
     print(response.css('title::text').get())
@@ -139,7 +147,7 @@ async def main() -> None:
     spider = StaticSpider(urls=['https://quotes.toscrape.com'], parse=parse)
     await spider.run()
 
-trio.run(main)
+anyio.run(main)
 ```
 
 Now we have `Quotes to Scrape` printed, yeah! You will notice the pseudo-selector `::text` for the css method and the
@@ -181,11 +189,11 @@ static_spider = StaticSpider(urls=['https://quotes.toscrape.com'], parse=parse)
 static_spider.run()
 ```
 
-With trio:
+With anyio:
 
 ```python
-import trio
-from scalpel.trionic import StaticResponse, StaticSpider
+import anyio
+from scalpel.any_io import StaticResponse, StaticSpider
 
 async def parse(spider: StaticSpider, response: StaticResponse) -> None:
     for quote in response.xpath('//div[@class="quote"]'):
@@ -195,7 +203,7 @@ async def main() -> None:
     spider = StaticSpider(urls=['https://quotes.toscrape.com'], parse=parse)
     await spider.run()
 
-trio.run(main)
+anyio.run(main)
 ```
 
 We will see an output like the following (I truncated it here):
@@ -235,11 +243,11 @@ static_spider = StaticSpider(urls=['https://quotes.toscrape.com'], parse=parse)
 static_spider.run()
 ```
 
-With trio:
+With anyio:
 
 ```python
-import trio
-from scalpel.trionic import StaticResponse, StaticSpider
+import anyio
+from scalpel.any_io import StaticResponse, StaticSpider
 
 async def parse(spider: StaticSpider, response: StaticResponse) -> None:
     for quote in response.xpath('//div[@class="quote"]'):
@@ -252,7 +260,7 @@ async def main() -> None:
     spider = StaticSpider(urls=['https://quotes.toscrape.com'], parse=parse)
     await spider.run()
 
-trio.run(main)
+anyio.run(main)
 ```
 
 We have the following output (I truncated it here):
@@ -306,12 +314,12 @@ static_spider = StaticSpider(urls=['https://quotes.toscrape.com'], parse=parse,
 static_spider.run()
 ```
 
-With trio:
+With anyio:
 
 ```python
-import trio
+import anyio
 from scalpel import Configuration
-from scalpel.trionic import StaticResponse, StaticSpider
+from scalpel.any_io import StaticResponse, StaticSpider
 
 async def parse(spider: StaticSpider, response: StaticResponse) -> None:
     for quote in response.xpath('//div[@class="quote"]'):
@@ -327,7 +335,7 @@ async def main() -> None:
     spider = StaticSpider(urls=['https://quotes.toscrape.com'], parse=parse, config=config)
     await spider.run()
 
-trio.run(main)
+anyio.run(main)
 ```
 
 !!! note
@@ -347,17 +355,17 @@ for quote in read_mp('/path/to/file.mp'):
     print(quote)
 ```
 
-With trio:
+With anyio:
 
 ```python
-import trio
-from scalpel.trionic import read_mp
+import anyio
+from scalpel.any_io import read_mp
 
 async def main() -> None:
     async for quote in read_mp('/path/to/file.mp'):
         print(quote)
 
-trio.run(main)
+anyio.run(main)
 ```
 
 Yeah! Now we have useful data that we can exploit.
@@ -410,12 +418,12 @@ static_spider.run()
 print(static_spider.statistics())
 ```
 
-With trio:
+With anyio:
 
 ```python
-import trio
+import anyio
 from scalpel import Configuration
-from scalpel.trionic import StaticResponse, StaticSpider
+from scalpel.any_io import StaticResponse, StaticSpider
 
 async def parse(spider: StaticSpider, response: StaticResponse) -> None:
     for quote in response.xpath('//div[@class="quote"]'):
@@ -438,10 +446,10 @@ async def main() -> None:
     # we print some statistics about the crawl operation
     print(spider.statistics())
 
-trio.run(main)
+anyio.run(main)
 ```
 
-There we goo! So now, if you read the file created, *data.mp* in the example case, you will get all quote information from
+There we go! So now, if you read the file created, *data.mp* in the example case, you will get all quote information from
 the first page to the last page. Don't hesitate to look at the 
 [examples](https://github.com/lewoudar/scalpel/tree/master/examples) folder for more code snippets to view.
 
@@ -473,7 +481,7 @@ use it when appropriate.
 
 Also, if you choose the follow *robots.txt* rules, keep in mind that for gevent spiders, the delay specified in this file
 will not be taken in account due to a technical limitation I don't explain for now in gevent. It is always the property
-`Configuration.request_delay` which is used for the delay between requests. The trio spiders do not suffer from this
+`Configuration.request_delay` which is used for the delay between requests. The anyio spiders do not suffer from this
 limitation.
 
 Furthermore, if you want a more object-oriented approach for your spider than a function, you can always use a class.
@@ -495,11 +503,11 @@ spider = StaticSpider(urls=['http://quotes.toscrape.com'], parse=Parser())
 spider.run()
 ```
 
-With trio:
+With anyio:
 
 ```python
-import trio
-from scalpel.trionic import StaticResponse, StaticSpider
+import anyio
+from scalpel.any_io import StaticResponse, StaticSpider
 
 
 class Parser:
@@ -511,5 +519,5 @@ async def main():
     spider = StaticSpider(urls=['http://quotes.toscrape.com'], parse=Parser())
     await spider.run()
 
-trio.run(main)
+anyio.run(main)
 ```
\ No newline at end of file
diff --git a/examples/selenium/trionic/__init__.py b/examples/selenium/any_io/__init__.py
similarity index 100%
rename from examples/selenium/trionic/__init__.py
rename to examples/selenium/any_io/__init__.py
diff --git a/examples/selenium/trionic/httpbin.py b/examples/selenium/any_io/httpbin.py
similarity index 95%
rename from examples/selenium/trionic/httpbin.py
rename to examples/selenium/any_io/httpbin.py
index f69fe23..2b803ab 100644
--- a/examples/selenium/trionic/httpbin.py
+++ b/examples/selenium/any_io/httpbin.py
@@ -1,10 +1,10 @@
 from datetime import datetime
 from pathlib import Path
 
-import trio
+import anyio
 
 from scalpel import Configuration, datetime_decoder
-from scalpel.trionic import SeleniumSpider, SeleniumResponse, read_mp
+from scalpel.any_io import SeleniumSpider, SeleniumResponse, read_mp
 
 
 async def parse(spider: SeleniumSpider, response: SeleniumResponse) -> None:
@@ -54,4 +54,4 @@ async def main() -> None:
 
 
 if __name__ == '__main__':
-    trio.run(main)
+    anyio.run(main)
diff --git a/examples/selenium/trionic/quotes_to_scrape.py b/examples/selenium/any_io/quotes_to_scrape.py
similarity index 90%
rename from examples/selenium/trionic/quotes_to_scrape.py
rename to examples/selenium/any_io/quotes_to_scrape.py
index f655865..ace737d 100644
--- a/examples/selenium/trionic/quotes_to_scrape.py
+++ b/examples/selenium/any_io/quotes_to_scrape.py
@@ -1,12 +1,12 @@
-"""Simple example to show usage of trio SeleniumSpider class"""
+"""Simple example to show usage of anyio SeleniumSpider class"""
 from datetime import datetime
 from pathlib import Path
 
-import trio
+import anyio
 from selenium.common.exceptions import NoSuchElementException
 
 from scalpel import Configuration, datetime_decoder
-from scalpel.trionic import SeleniumSpider, SeleniumResponse, read_mp
+from scalpel.any_io import SeleniumSpider, SeleniumResponse, read_mp
 
 
 async def parse(spider: SeleniumSpider, response: SeleniumResponse) -> None:
@@ -45,4 +45,4 @@ async def main() -> None:
 
 
 if __name__ == '__main__':
-    trio.run(main)
+    anyio.run(main)
diff --git a/examples/static/trionic.py b/examples/static/any_io.py
similarity index 87%
rename from examples/static/trionic.py
rename to examples/static/any_io.py
index 167c136..13df9d3 100644
--- a/examples/static/trionic.py
+++ b/examples/static/any_io.py
@@ -1,11 +1,11 @@
-"""Simple example to show how to use the trio StaticSpider class"""
+"""Simple example to show how to use the anyio StaticSpider class"""
 from datetime import datetime
 from pathlib import Path
 
-import trio
+import anyio
 
 from scalpel import Configuration
-from scalpel.trionic import StaticResponse, StaticSpider, read_mp
+from scalpel.any_io import StaticResponse, StaticSpider, read_mp
 
 
 async def parse(spider: StaticSpider, response: StaticResponse) -> None:
@@ -39,4 +39,4 @@ async def main() -> None:
 
 
 if __name__ == '__main__':
-    trio.run(main)
+    anyio.run(main)
diff --git a/mkdocs.yml b/mkdocs.yml
index 6386b3f..9578c10 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -26,7 +26,8 @@ markdown_extensions:
       permalink: true
   - admonition
   - mkautodoc
-  - codehilite
+  - codehilite:
+      css_class: highlight
 
 extra_css:
   - css/custom.css
\ No newline at end of file
diff --git a/noxfile.py b/noxfile.py
index 82b71b6..b08f305 100644
--- a/noxfile.py
+++ b/noxfile.py
@@ -25,9 +25,9 @@ def tests(session):
     """
     Runs the test suite.
     You can also run a part of the test suite by specifying the parts you want to test. The values "core", "green"
-    and "trionic" are accepted as extra arguments. They can be cumulated.
+    and "any_io" are accepted as extra arguments. They can be cumulated.
     """
-    to_test = ['core', 'trionic', 'green']
+    to_test = ['core', 'any_io', 'green']
     for item in session.posargs:
         if item not in to_test:
             session.error(f'{item} is not part of {to_test}')
@@ -50,7 +50,8 @@ def tests(session):
 @nox.session(python=PYTHON_VERSIONS[-1])
 def docs(session):
     """Builds the documentation."""
-    session.install('mkdocs==1.0.4')
+    session.install('poetry>=1.0.0,<2.0.0')
+    session.run('poetry', 'install')
     session.run('mkdocs', 'build', '--clean')
 
 
diff --git a/poetry.lock b/poetry.lock
index 9667c99..dbb1143 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,59 +1,68 @@
 [[package]]
-category = "dev"
-description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+name = "anyio"
+version = "3.0.1"
+description = "High level compatibility layer for multiple asynchronous event loop implementations"
+category = "main"
+optional = false
+python-versions = ">=3.6.2"
+
+[package.dependencies]
+async-generator = {version = "*", markers = "python_version < \"3.7\""}
+dataclasses = {version = "*", markers = "python_version < \"3.7\""}
+idna = ">=2.8"
+sniffio = ">=1.1"
+typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
+
+[package.extras]
+doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"]
+test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=6.0)", "trustme", "uvloop (<0.15)", "uvloop (>=0.15)"]
+trio = ["trio (>=0.16)"]
+
+[[package]]
 name = "appdirs"
+version = "1.4.4"
+description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+category = "dev"
 optional = false
 python-versions = "*"
-version = "1.4.4"
 
 [[package]]
-category = "dev"
-description = "Bash tab completion for argparse"
 name = "argcomplete"
+version = "1.12.3"
+description = "Bash tab completion for argparse"
+category = "dev"
 optional = false
 python-versions = "*"
-version = "1.12.1"
 
 [package.dependencies]
-[package.dependencies.importlib-metadata]
-python = ">=3.6,<3.7"
-version = ">=0.23,<3"
+importlib-metadata = { version = ">=0.23,<5", markers = "python_version == \"3.6\" or python_version == \"3.7\"" }
 
 [package.extras]
 test = ["coverage", "flake8", "pexpect", "wheel"]
 
 [[package]]
-category = "main"
-description = "Async generators and context managers for Python 3.5+"
 name = "async-generator"
-optional = false
-python-versions = ">=3.5"
 version = "1.10"
-
-[[package]]
-category = "dev"
-description = "Enhance the standard unittest package with features for testing asyncio libraries"
-name = "asynctest"
+description = "Async generators and context managers for Python 3.5+"
+category = "main"
 optional = false
 python-versions = ">=3.5"
-version = "0.13.0"
 
 [[package]]
-category = "dev"
-description = "Atomic file writes."
-marker = "sys_platform == \"win32\""
 name = "atomicwrites"
+version = "1.4.0"
+description = "Atomic file writes."
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.4.0"
 
 [[package]]
-category = "main"
-description = "Classes Without Boilerplate"
 name = "attrs"
+version = "19.3.0"
+description = "Classes Without Boilerplate"
+category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "19.3.0"
 
 [package.extras]
 azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"]
@@ -62,377 +71,335 @@ docs = ["sphinx", "zope.interface"]
 tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
 
 [[package]]
-category = "dev"
-description = "Security oriented static analyser for python code."
 name = "bandit"
+version = "1.7.0"
+description = "Security oriented static analyser for python code."
+category = "dev"
 optional = false
-python-versions = "*"
-version = "1.6.2"
+python-versions = ">=3.5"
 
 [package.dependencies]
+colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""}
 GitPython = ">=1.0.1"
-PyYAML = ">=3.13"
-colorama = ">=0.3.9"
+PyYAML = ">=5.3.1"
 six = ">=1.10.0"
 stevedore = ">=1.20.0"
 
 [[package]]
-category = "main"
-description = "Python package for providing Mozilla's CA Bundle."
 name = "certifi"
+version = "2020.12.5"
+description = "Python package for providing Mozilla's CA Bundle."
+category = "main"
 optional = false
 python-versions = "*"
-version = "2020.6.20"
 
 [[package]]
-category = "main"
-description = "Foreign Function Interface for Python calling C code."
-marker = "platform_python_implementation == \"CPython\" and sys_platform == \"win32\" or platform_python_implementation == \"CPython\" or os_name == \"nt\" and implementation_name != \"pypy\""
 name = "cffi"
-optional = false
+version = "1.14.5"
+description = "Foreign Function Interface for Python calling C code."
+category = "main"
+optional = true
 python-versions = "*"
-version = "1.14.3"
 
 [package.dependencies]
 pycparser = "*"
 
 [[package]]
-category = "main"
-description = "Universal encoding detector for Python 2 and 3"
 name = "chardet"
+version = "4.0.0"
+description = "Universal encoding detector for Python 2 and 3"
+category = "dev"
 optional = false
-python-versions = "*"
-version = "3.0.4"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
 [[package]]
-category = "dev"
-description = "Composable command line interface toolkit"
 name = "click"
+version = "7.1.2"
+description = "Composable command line interface toolkit"
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "7.1.2"
 
 [[package]]
-category = "dev"
-description = "Hosted coverage reports for GitHub, Bitbucket and Gitlab"
 name = "codecov"
+version = "2.1.11"
+description = "Hosted coverage reports for GitHub, Bitbucket and Gitlab"
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "2.1.10"
 
 [package.dependencies]
 coverage = "*"
 requests = ">=2.7.9"
 
 [[package]]
-category = "dev"
-description = "Cross-platform colored terminal text."
-marker = "sys_platform == \"win32\" or platform_system == \"Windows\""
 name = "colorama"
+version = "0.4.4"
+description = "Cross-platform colored terminal text."
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "0.4.4"
 
 [[package]]
-category = "dev"
-description = "Log formatting with colors!"
 name = "colorlog"
+version = "4.8.0"
+description = "Log formatting with colors!"
+category = "dev"
 optional = false
 python-versions = "*"
-version = "4.4.0"
 
 [package.dependencies]
-colorama = "*"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
 
 [[package]]
-category = "main"
-description = "A configuration management toolkit"
 name = "configuror"
+version = "0.2.0"
+description = "A configuration management toolkit"
+category = "main"
 optional = false
 python-versions = ">=3.6,<4.0"
-version = "0.2.0"
 
 [package.dependencies]
 pyyaml = ">=5.2,<6.0"
 toml = ">=0.10.0,<0.11.0"
 
 [[package]]
-category = "main"
-description = "PEP 567 Backport"
-marker = "python_version < \"3.7\""
 name = "contextvars"
+version = "2.4"
+description = "PEP 567 Backport"
+category = "main"
 optional = false
 python-versions = "*"
-version = "2.4"
 
 [package.dependencies]
 immutables = ">=0.9"
 
 [[package]]
-category = "dev"
-description = "Code coverage measurement for Python"
 name = "coverage"
+version = "5.5"
+description = "Code coverage measurement for Python"
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
-version = "5.3"
 
 [package.extras]
 toml = ["toml"]
 
 [[package]]
-category = "main"
-description = "cssselect parses CSS3 Selectors and translates them to XPath 1.0"
 name = "cssselect"
+version = "1.1.0"
+description = "cssselect parses CSS3 Selectors and translates them to XPath 1.0"
+category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.1.0"
 
 [[package]]
-category = "dev"
-description = "Distribution utilities"
-name = "distlib"
+name = "dataclasses"
+version = "0.8"
+description = "A backport of the dataclasses module for Python 3.6"
+category = "main"
 optional = false
-python-versions = "*"
-version = "0.3.1"
+python-versions = ">=3.6, <3.7"
 
 [[package]]
-category = "main"
-description = "DNS toolkit"
-name = "dnspython"
-optional = true
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.16.0"
-
-[package.extras]
-DNSSEC = ["pycryptodome", "ecdsa (>=0.13)"]
-IDNA = ["idna (>=2.1)"]
+name = "distlib"
+version = "0.3.1"
+description = "Distribution utilities"
+category = "dev"
+optional = false
+python-versions = "*"
 
 [[package]]
-category = "main"
-description = "Up to date simple useragent faker with real world database"
 name = "fake-useragent"
+version = "0.1.11"
+description = "Up to date simple useragent faker with real world database"
+category = "main"
 optional = false
 python-versions = "*"
-version = "0.1.11"
 
 [[package]]
-category = "dev"
-description = "A platform independent file lock."
 name = "filelock"
+version = "3.0.12"
+description = "A platform independent file lock."
+category = "dev"
 optional = false
 python-versions = "*"
-version = "3.0.12"
 
 [[package]]
-category = "dev"
-description = "the modular source code checker: pep8 pyflakes and co"
 name = "flake8"
+version = "3.9.1"
+description = "the modular source code checker: pep8 pyflakes and co"
+category = "dev"
 optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
-version = "3.8.4"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
 
 [package.dependencies]
+importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
 mccabe = ">=0.6.0,<0.7.0"
-pycodestyle = ">=2.6.0a1,<2.7.0"
-pyflakes = ">=2.2.0,<2.3.0"
-
-[package.dependencies.importlib-metadata]
-python = "<3.8"
-version = "*"
+pycodestyle = ">=2.7.0,<2.8.0"
+pyflakes = ">=2.3.0,<2.4.0"
 
 [[package]]
-category = "dev"
-description = "Clean single-source support for Python 3 and 2"
 name = "future"
+version = "0.18.2"
+description = "Clean single-source support for Python 3 and 2"
+category = "dev"
 optional = false
 python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
-version = "0.18.2"
 
 [[package]]
-category = "main"
-description = "Coroutine-based network library"
 name = "gevent"
+version = "20.12.1"
+description = "Coroutine-based network library"
+category = "main"
 optional = true
 python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
-version = "20.9.0"
 
 [package.dependencies]
-cffi = ">=1.12.2"
-greenlet = ">=0.4.17"
-setuptools = "*"
+cffi = {version = ">=1.12.2", markers = "platform_python_implementation == \"CPython\" and sys_platform == \"win32\""}
+greenlet = {version = ">=0.4.17,<2.0", markers = "platform_python_implementation == \"CPython\""}
 "zope.event" = "*"
 "zope.interface" = "*"
 
-[package.dependencies.dnspython]
-optional = true
-version = ">=1.16.0,<2.0"
-
-[package.dependencies.idna]
-optional = true
-version = "*"
-
-[package.dependencies.psutil]
-optional = true
-version = ">=5.7.0"
-
 [package.extras]
 dnspython = ["dnspython (>=1.16.0,<2.0)", "idna"]
 docs = ["repoze.sphinx.autointerface", "sphinxcontrib-programoutput"]
 monitor = ["psutil (>=5.7.0)"]
 recommended = ["dnspython (>=1.16.0,<2.0)", "idna", "cffi (>=1.12.2)", "selectors2", "backports.socketpair", "psutil (>=5.7.0)"]
-test = ["dnspython (>=1.16.0,<2.0)", "idna", "requests", "objgraph", "cffi (>=1.12.2)", "selectors2", "futures", "mock", "backports.socketpair", "contextvars (2.4)", "coverage (<5.0)", "coveralls (>=1.7.0)", "psutil (>=5.7.0)"]
+test = ["dnspython (>=1.16.0,<2.0)", "idna", "requests", "objgraph", "cffi (>=1.12.2)", "selectors2", "futures", "mock", "backports.socketpair", "contextvars (==2.4)", "coverage (>=5.0)", "coveralls (>=1.7.0)", "psutil (>=5.7.0)"]
 
 [[package]]
-category = "dev"
-description = "Git Object Database"
 name = "gitdb"
+version = "4.0.7"
+description = "Git Object Database"
+category = "dev"
 optional = false
 python-versions = ">=3.4"
-version = "4.0.5"
 
 [package.dependencies]
-smmap = ">=3.0.1,<4"
+smmap = ">=3.0.1,<5"
 
 [[package]]
-category = "dev"
-description = "Python Git Library"
 name = "gitpython"
+version = "3.1.15"
+description = "Python Git Library"
+category = "dev"
 optional = false
-python-versions = ">=3.4"
-version = "3.1.11"
+python-versions = ">=3.5"
 
 [package.dependencies]
 gitdb = ">=4.0.1,<5"
+typing-extensions = ">=3.7.4.0"
 
 [[package]]
-category = "main"
-description = "Lightweight in-process concurrent programming"
-marker = "platform_python_implementation == \"CPython\""
 name = "greenlet"
+version = "1.0.0"
+description = "Lightweight in-process concurrent programming"
+category = "main"
 optional = true
-python-versions = "*"
-version = "0.4.17"
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
+
+[package.extras]
+docs = ["sphinx"]
 
 [[package]]
-category = "main"
-description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
 name = "h11"
+version = "0.12.0"
+description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
+category = "main"
 optional = false
-python-versions = "*"
-version = "0.9.0"
+python-versions = ">=3.6"
 
 [[package]]
+name = "httpcore"
+version = "0.12.3"
+description = "A minimal low-level HTTP client."
 category = "main"
-description = "HTTP/2 State-Machine based protocol implementation"
-name = "h2"
 optional = false
-python-versions = "*"
-version = "3.2.0"
+python-versions = ">=3.6"
 
 [package.dependencies]
-hpack = ">=3.0,<4"
-hyperframe = ">=5.2.0,<6"
-
-[[package]]
-category = "main"
-description = "Pure-Python HPACK header compression"
-name = "hpack"
-optional = false
-python-versions = "*"
-version = "3.0.0"
+h11 = "<1.0.0"
+sniffio = ">=1.0.0,<2.0.0"
 
-[[package]]
-category = "main"
-description = "Chromium HSTS Preload list as a Python package and updated daily"
-name = "hstspreload"
-optional = false
-python-versions = ">=3.6"
-version = "2020.10.20"
+[package.extras]
+http2 = ["h2 (>=3,<5)"]
 
 [[package]]
-category = "main"
-description = "The next generation HTTP client."
 name = "httpx"
+version = "0.17.1"
+description = "The next generation HTTP client."
+category = "main"
 optional = false
 python-versions = ">=3.6"
-version = "0.12.1"
 
 [package.dependencies]
 certifi = "*"
-chardet = ">=3.0.0,<4.0.0"
-h11 = ">=0.8,<0.10"
-h2 = ">=3.0.0,<4.0.0"
-hstspreload = "*"
-idna = ">=2.0.0,<3.0.0"
-rfc3986 = ">=1.3,<2"
-sniffio = ">=1.0.0,<2.0.0"
-urllib3 = ">=1.0.0,<2.0.0"
+httpcore = ">=0.12.1,<0.13"
+rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]}
+sniffio = "*"
 
-[[package]]
-category = "main"
-description = "HTTP/2 framing layer for Python"
-name = "hyperframe"
-optional = false
-python-versions = "*"
-version = "5.2.0"
+[package.extras]
+brotli = ["brotlipy (>=0.7.0,<0.8.0)"]
+http2 = ["h2 (>=3.0.0,<4.0.0)"]
 
 [[package]]
-category = "main"
-description = "Internationalized Domain Names in Applications (IDNA)"
 name = "idna"
+version = "2.10"
+description = "Internationalized Domain Names in Applications (IDNA)"
+category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "2.10"
 
 [[package]]
-category = "main"
-description = "Immutable Collections"
-marker = "python_version < \"3.7\""
 name = "immutables"
+version = "0.15"
+description = "Immutable Collections"
+category = "main"
 optional = false
 python-versions = ">=3.5"
-version = "0.14"
+
+[package.extras]
+test = ["flake8 (>=3.8.4,<3.9.0)", "pycodestyle (>=2.6.0,<2.7.0)"]
 
 [[package]]
-category = "dev"
-description = "Read metadata from Python packages"
-marker = "python_version < \"3.8\""
 name = "importlib-metadata"
+version = "4.0.1"
+description = "Read metadata from Python packages"
+category = "dev"
 optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
-version = "2.0.0"
+python-versions = ">=3.6"
 
 [package.dependencies]
+typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
 zipp = ">=0.5"
 
 [package.extras]
-docs = ["sphinx", "rst.linker"]
-testing = ["packaging", "pep517", "importlib-resources (>=1.3)"]
+docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
+testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
 
 [[package]]
-category = "dev"
-description = "Read resources from Python packages"
-marker = "python_version < \"3.7\""
 name = "importlib-resources"
+version = "5.1.2"
+description = "Read resources from Python packages"
+category = "dev"
 optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
-version = "3.3.0"
+python-versions = ">=3.6"
 
 [package.dependencies]
-[package.dependencies.zipp]
-python = "<3.8"
-version = ">=0.4"
+zipp = {version = ">=0.4", markers = "python_version < \"3.8\""}
 
 [package.extras]
-docs = ["sphinx", "rst.linker", "jaraco.packaging"]
+docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
+testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "pytest-black (>=0.3.7)", "pytest-mypy"]
 
 [[package]]
-category = "dev"
-description = "A very fast and expressive template engine."
 name = "jinja2"
+version = "2.11.3"
+description = "A very fast and expressive template engine."
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "2.11.2"
 
 [package.dependencies]
 MarkupSafe = ">=0.23"
@@ -441,56 +408,48 @@ MarkupSafe = ">=0.23"
 i18n = ["Babel (>=0.8)"]
 
 [[package]]
-category = "dev"
-description = "Lightweight pipelining: using Python functions as pipeline jobs."
-marker = "python_version > \"2.7\""
 name = "joblib"
+version = "1.0.1"
+description = "Lightweight pipelining with Python functions"
+category = "dev"
 optional = false
 python-versions = ">=3.6"
-version = "0.17.0"
 
 [[package]]
-category = "dev"
-description = "Python LiveReload is an awesome tool for web developers"
 name = "livereload"
+version = "2.6.3"
+description = "Python LiveReload is an awesome tool for web developers"
+category = "dev"
 optional = false
 python-versions = "*"
-version = "2.6.3"
 
 [package.dependencies]
 six = "*"
-
-[package.dependencies.tornado]
-python = ">=2.8"
-version = "*"
+tornado = {version = "*", markers = "python_version > \"2.7\""}
 
 [[package]]
-category = "dev"
-description = "A Python implementation of Lunr.js"
 name = "lunr"
+version = "0.5.8"
+description = "A Python implementation of Lunr.js"
+category = "dev"
 optional = false
 python-versions = "*"
-version = "0.5.8"
 
 [package.dependencies]
 future = ">=0.16.0"
+nltk = {version = ">=3.2.5", optional = true, markers = "python_version > \"2.7\" and extra == \"languages\""}
 six = ">=1.11.0"
 
-[package.dependencies.nltk]
-optional = true
-python = ">=2.8"
-version = ">=3.2.5"
-
 [package.extras]
 languages = ["nltk (>=3.2.5,<3.5)", "nltk (>=3.2.5)"]
 
 [[package]]
-category = "main"
-description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
 name = "lxml"
+version = "4.6.3"
+description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
+category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*"
-version = "4.6.1"
 
 [package.extras]
 cssselect = ["cssselect (>=0.7)"]
@@ -499,128 +458,122 @@ htmlsoup = ["beautifulsoup4"]
 source = ["Cython (>=0.29.7)"]
 
 [[package]]
-category = "dev"
-description = "Python implementation of Markdown."
 name = "markdown"
+version = "3.3.4"
+description = "Python implementation of Markdown."
+category = "dev"
 optional = false
 python-versions = ">=3.6"
-version = "3.3.3"
 
 [package.dependencies]
-[package.dependencies.importlib-metadata]
-python = "<3.8"
-version = "*"
+importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
 
 [package.extras]
 testing = ["coverage", "pyyaml"]
 
 [[package]]
-category = "dev"
-description = "Safely add untrusted strings to HTML/XML markup."
 name = "markupsafe"
+version = "1.1.1"
+description = "Safely add untrusted strings to HTML/XML markup."
+category = "dev"
 optional = false
 python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
-version = "1.1.1"
 
 [[package]]
-category = "dev"
-description = "McCabe checker, plugin for flake8"
 name = "mccabe"
+version = "0.6.1"
+description = "McCabe checker, plugin for flake8"
+category = "dev"
 optional = false
 python-versions = "*"
-version = "0.6.1"
 
 [[package]]
-category = "dev"
-description = "AutoDoc for MarkDown"
 name = "mkautodoc"
+version = "0.1.0"
+description = "AutoDoc for MarkDown"
+category = "dev"
 optional = false
 python-versions = ">=3.6"
-version = "0.1.0"
 
 [[package]]
-category = "dev"
-description = "Project documentation with Markdown."
 name = "mkdocs"
+version = "1.1.2"
+description = "Project documentation with Markdown."
+category = "dev"
 optional = false
 python-versions = ">=3.5"
-version = "1.1.2"
 
 [package.dependencies]
+click = ">=3.3"
 Jinja2 = ">=2.10.1"
+livereload = ">=2.5.1"
+lunr = {version = "0.5.8", extras = ["languages"]}
 Markdown = ">=3.2.1"
 PyYAML = ">=3.10"
-click = ">=3.3"
-livereload = ">=2.5.1"
 tornado = ">=5.0"
 
-[package.dependencies.lunr]
-extras = ["languages"]
-version = "0.5.8"
-
 [[package]]
-category = "dev"
-description = "A Material Design theme for MkDocs"
 name = "mkdocs-material"
+version = "7.1.3"
+description = "A Material Design theme for MkDocs"
+category = "dev"
 optional = false
 python-versions = "*"
-version = "6.1.2"
 
 [package.dependencies]
-Pygments = ">=2.4"
 markdown = ">=3.2"
 mkdocs = ">=1.1"
 mkdocs-material-extensions = ">=1.0"
+Pygments = ">=2.4"
 pymdown-extensions = ">=7.0"
 
 [[package]]
-category = "dev"
-description = "Extension pack for Python Markdown."
 name = "mkdocs-material-extensions"
+version = "1.0.1"
+description = "Extension pack for Python Markdown."
+category = "dev"
 optional = false
 python-versions = ">=3.5"
-version = "1.0.1"
 
 [package.dependencies]
 mkdocs-material = ">=5.0.0"
 
 [[package]]
-category = "dev"
-description = "Rolling backport of unittest.mock for all Pythons"
 name = "mock"
+version = "4.0.3"
+description = "Rolling backport of unittest.mock for all Pythons"
+category = "dev"
 optional = false
 python-versions = ">=3.6"
-version = "4.0.2"
 
 [package.extras]
 build = ["twine", "wheel", "blurb"]
 docs = ["sphinx"]
-test = ["pytest", "pytest-cov"]
+test = ["pytest (<5.4)", "pytest-cov"]
 
 [[package]]
-category = "dev"
-description = "More routines for operating on iterables, beyond itertools"
 name = "more-itertools"
+version = "8.7.0"
+description = "More routines for operating on iterables, beyond itertools"
+category = "dev"
 optional = false
 python-versions = ">=3.5"
-version = "8.6.0"
 
 [[package]]
-category = "main"
-description = "MessagePack (de)serializer."
 name = "msgpack"
+version = "1.0.2"
+description = "MessagePack (de)serializer."
+category = "main"
 optional = false
 python-versions = "*"
-version = "1.0.0"
 
 [[package]]
-category = "dev"
-description = "Natural Language Toolkit"
-marker = "python_version > \"2.7\""
 name = "nltk"
+version = "3.6.2"
+description = "Natural Language Toolkit"
+category = "dev"
 optional = false
-python-versions = "*"
-version = "3.5"
+python-versions = ">=3.5.*"
 
 [package.dependencies]
 click = "*"
@@ -629,20 +582,20 @@ regex = "*"
 tqdm = "*"
 
 [package.extras]
-all = ["requests", "numpy", "python-crfsuite", "scikit-learn", "twython", "pyparsing", "scipy", "matplotlib", "gensim"]
+all = ["matplotlib", "twython", "scipy", "numpy", "gensim (<4.0.0)", "python-crfsuite", "pyparsing", "scikit-learn", "requests"]
 corenlp = ["requests"]
-machine_learning = ["gensim", "numpy", "python-crfsuite", "scikit-learn", "scipy"]
+machine_learning = ["gensim (<4.0.0)", "numpy", "python-crfsuite", "scikit-learn", "scipy"]
 plot = ["matplotlib"]
 tgrep = ["pyparsing"]
 twitter = ["twython"]
 
 [[package]]
-category = "dev"
-description = "Flexible test automation."
 name = "nox"
+version = "2019.11.9"
+description = "Flexible test automation."
+category = "dev"
 optional = false
 python-versions = ">=3.5"
-version = "2019.11.9"
 
 [package.dependencies]
 argcomplete = ">=1.9.4,<2.0"
@@ -654,35 +607,34 @@ virtualenv = ">=14.0.0"
 tox_to_nox = ["jinja2", "tox"]
 
 [[package]]
-category = "main"
-description = "Capture the outcome of Python function calls."
 name = "outcome"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.0.1"
+version = "1.1.0"
+description = "Capture the outcome of Python function calls."
+category = "main"
+optional = true
+python-versions = ">=3.6"
 
 [package.dependencies]
 attrs = ">=19.2.0"
 
 [[package]]
-category = "dev"
-description = "Core utilities for Python packages"
 name = "packaging"
+version = "20.9"
+description = "Core utilities for Python packages"
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "20.4"
 
 [package.dependencies]
 pyparsing = ">=2.0.2"
-six = "*"
 
 [[package]]
-category = "main"
-description = "Parsel is a library to extract data from HTML and XML using XPath and CSS selectors"
 name = "parsel"
+version = "1.6.0"
+description = "Parsel is a library to extract data from HTML and XML using XPath and CSS selectors"
+category = "main"
 optional = false
 python-versions = "*"
-version = "1.6.0"
 
 [package.dependencies]
 cssselect = ">=0.9"
@@ -691,134 +643,116 @@ six = ">=1.6.0"
 w3lib = ">=1.19.0"
 
 [[package]]
-category = "dev"
-description = "Python Build Reasonableness"
 name = "pbr"
+version = "5.6.0"
+description = "Python Build Reasonableness"
+category = "dev"
 optional = false
 python-versions = ">=2.6"
-version = "5.5.1"
 
 [[package]]
-category = "dev"
-description = "plugin and hook calling mechanisms for python"
 name = "pluggy"
+version = "0.13.1"
+description = "plugin and hook calling mechanisms for python"
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "0.13.1"
 
 [package.dependencies]
-[package.dependencies.importlib-metadata]
-python = "<3.8"
-version = ">=0.12"
+importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
 
 [package.extras]
 dev = ["pre-commit", "tox"]
 
 [[package]]
-category = "main"
-description = "Cross-platform lib for process and system monitoring in Python."
-marker = "(sys_platform != \"win32\" or platform_python_implementation == \"CPython\")"
-name = "psutil"
-optional = true
-python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "5.7.3"
-
-[package.extras]
-test = ["ipaddress", "mock", "unittest2", "enum34", "pywin32", "wmi"]
-
-[[package]]
-category = "dev"
-description = "library with cross-python path, ini-parsing, io, code, log facilities"
 name = "py"
+version = "1.10.0"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.9.0"
 
 [[package]]
-category = "dev"
-description = "Python style guide checker"
 name = "pycodestyle"
+version = "2.7.0"
+description = "Python style guide checker"
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "2.6.0"
 
 [[package]]
-category = "main"
-description = "C parser in Python"
-marker = "platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and os_name == \"nt\" and implementation_name != \"pypy\" or platform_python_implementation == \"CPython\" and os_name == \"nt\" and implementation_name != \"pypy\" or os_name == \"nt\" and implementation_name != \"pypy\""
 name = "pycparser"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 version = "2.20"
+description = "C parser in Python"
+category = "main"
+optional = true
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
-category = "dev"
-description = "passive checker of Python programs"
 name = "pyflakes"
+version = "2.3.1"
+description = "passive checker of Python programs"
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "2.2.0"
 
 [[package]]
-category = "dev"
-description = "Pygments is a syntax highlighting package written in Python."
 name = "pygments"
+version = "2.8.1"
+description = "Pygments is a syntax highlighting package written in Python."
+category = "dev"
 optional = false
 python-versions = ">=3.5"
-version = "2.7.2"
 
 [[package]]
-category = "dev"
-description = "Extension pack for Python Markdown."
 name = "pymdown-extensions"
+version = "8.1.1"
+description = "Extension pack for Python Markdown."
+category = "dev"
 optional = false
-python-versions = ">=3.5"
-version = "8.0.1"
+python-versions = ">=3.6"
 
 [package.dependencies]
 Markdown = ">=3.2"
 
 [[package]]
-category = "dev"
-description = "Python parsing module"
 name = "pyparsing"
+version = "2.4.7"
+description = "Python parsing module"
+category = "dev"
 optional = false
 python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
-version = "2.4.7"
 
 [[package]]
-category = "dev"
-description = "pytest: simple powerful testing with Python"
 name = "pytest"
+version = "5.4.3"
+description = "pytest: simple powerful testing with Python"
+category = "dev"
 optional = false
 python-versions = ">=3.5"
-version = "5.4.3"
 
 [package.dependencies]
-atomicwrites = ">=1.0"
+atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
 attrs = ">=17.4.0"
-colorama = "*"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
 more-itertools = ">=4.0.0"
 packaging = "*"
 pluggy = ">=0.12,<1.0"
 py = ">=1.5.0"
 wcwidth = "*"
 
-[package.dependencies.importlib-metadata]
-python = "<3.8"
-version = ">=0.12"
-
 [package.extras]
-checkqa-mypy = ["mypy (v0.761)"]
+checkqa-mypy = ["mypy (==v0.761)"]
 testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
 
 [[package]]
-category = "dev"
-description = "Thin-wrapper around the mock package for easier use with py.test"
 name = "pytest-mock"
+version = "2.0.0"
+description = "Thin-wrapper around the mock package for easier use with py.test"
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "2.0.0"
 
 [package.dependencies]
 pytest = ">=2.7"
@@ -827,285 +761,260 @@ pytest = ">=2.7"
 dev = ["pre-commit", "tox"]
 
 [[package]]
-category = "dev"
-description = "Pytest plugin for trio"
-name = "pytest-trio"
-optional = false
-python-versions = ">=3.5"
-version = "0.6.0"
-
-[package.dependencies]
-async-generator = ">=1.9"
-outcome = "*"
-pytest = ">=3.6"
-trio = ">=0.15.0"
-
-[[package]]
-category = "main"
-description = "YAML parser and emitter for Python"
 name = "pyyaml"
+version = "5.4.1"
+description = "YAML parser and emitter for Python"
+category = "main"
 optional = false
-python-versions = "*"
-version = "5.3.1"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
 
 [[package]]
-category = "dev"
-description = "Alternative regular expression module, to replace re."
-marker = "python_version > \"2.7\""
 name = "regex"
+version = "2021.4.4"
+description = "Alternative regular expression module, to replace re."
+category = "dev"
 optional = false
 python-versions = "*"
-version = "2020.10.28"
 
 [[package]]
-category = "dev"
-description = "Python HTTP for Humans."
 name = "requests"
+version = "2.25.1"
+description = "Python HTTP for Humans."
+category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "2.24.0"
 
 [package.dependencies]
 certifi = ">=2017.4.17"
-chardet = ">=3.0.2,<4"
+chardet = ">=3.0.2,<5"
 idna = ">=2.5,<3"
-urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26"
+urllib3 = ">=1.21.1,<1.27"
 
 [package.extras]
 security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"]
-socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"]
+socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
 
 [[package]]
-category = "dev"
-description = "A utility for mocking out the Python HTTPX library."
 name = "respx"
+version = "0.16.3"
+description = "A utility for mocking out the Python HTTPX and HTTP Core libraries."
+category = "dev"
 optional = false
 python-versions = ">=3.6"
-version = "0.10.1"
 
 [package.dependencies]
-asynctest = "*"
-httpx = ">=0.12,<0.13"
+httpx = ">=0.15"
 
 [[package]]
-category = "main"
-description = "Validating URI References per RFC 3986"
 name = "rfc3986"
+version = "1.4.0"
+description = "Validating URI References per RFC 3986"
+category = "main"
 optional = false
 python-versions = "*"
-version = "1.4.0"
+
+[package.dependencies]
+idna = {version = "*", optional = true, markers = "extra == \"idna2008\""}
 
 [package.extras]
 idna2008 = ["idna"]
 
 [[package]]
-category = "main"
-description = "Python bindings for Selenium"
 name = "selenium"
+version = "3.141.0"
+description = "Python bindings for Selenium"
+category = "main"
 optional = false
 python-versions = "*"
-version = "3.141.0"
 
 [package.dependencies]
 urllib3 = "*"
 
 [[package]]
-category = "main"
-description = "Python 2 and 3 compatibility utilities"
 name = "six"
+version = "1.15.0"
+description = "Python 2 and 3 compatibility utilities"
+category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
-version = "1.15.0"
 
 [[package]]
-category = "dev"
-description = "A pure Python implementation of a sliding window memory map manager"
 name = "smmap"
+version = "4.0.0"
+description = "A pure Python implementation of a sliding window memory map manager"
+category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "3.0.4"
+python-versions = ">=3.5"
 
 [[package]]
-category = "main"
-description = "Sniff out which async library your code is running under"
 name = "sniffio"
+version = "1.2.0"
+description = "Sniff out which async library your code is running under"
+category = "main"
 optional = false
 python-versions = ">=3.5"
-version = "1.2.0"
 
 [package.dependencies]
-[package.dependencies.contextvars]
-python = "<3.7"
-version = ">=2.1"
+contextvars = {version = ">=2.1", markers = "python_version < \"3.7\""}
 
 [[package]]
-category = "main"
-description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set"
 name = "sortedcontainers"
-optional = false
+version = "2.3.0"
+description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set"
+category = "main"
+optional = true
 python-versions = "*"
-version = "2.2.2"
 
 [[package]]
-category = "dev"
-description = "Manage dynamic plugins for Python applications"
 name = "stevedore"
+version = "3.3.0"
+description = "Manage dynamic plugins for Python applications"
+category = "dev"
 optional = false
 python-versions = ">=3.6"
-version = "3.2.2"
 
 [package.dependencies]
+importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""}
 pbr = ">=2.0.0,<2.1.0 || >2.1.0"
 
-[package.dependencies.importlib-metadata]
-python = "<3.8"
-version = ">=1.7.0"
-
 [[package]]
-category = "main"
-description = "Python Library for Tom's Obvious, Minimal Language"
 name = "toml"
+version = "0.10.2"
+description = "Python Library for Tom's Obvious, Minimal Language"
+category = "main"
 optional = false
 python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
-version = "0.10.2"
 
 [[package]]
-category = "dev"
-description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
 name = "tornado"
+version = "6.1"
+description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
+category = "dev"
 optional = false
 python-versions = ">= 3.5"
-version = "6.1"
 
 [[package]]
-category = "dev"
-description = "Fast, Extensible Progress Meter"
-marker = "python_version > \"2.7\""
 name = "tqdm"
+version = "4.60.0"
+description = "Fast, Extensible Progress Meter"
+category = "dev"
 optional = false
-python-versions = ">=2.6, !=3.0.*, !=3.1.*"
-version = "4.51.0"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
 
 [package.extras]
-dev = ["py-make (>=0.1.0)", "twine", "argopt", "pydoc-markdown"]
+dev = ["py-make (>=0.1.0)", "twine", "wheel"]
+notebook = ["ipywidgets (>=6)"]
+telegram = ["requests"]
 
 [[package]]
-category = "main"
-description = "A friendly Python library for async concurrency and I/O"
 name = "trio"
-optional = false
-python-versions = ">=3.6"
 version = "0.17.0"
+description = "A friendly Python library for async concurrency and I/O"
+category = "main"
+optional = true
+python-versions = ">=3.6"
 
 [package.dependencies]
 async-generator = ">=1.9"
 attrs = ">=19.2.0"
-cffi = ">=1.14"
+cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""}
+contextvars = {version = ">=2.1", markers = "python_version < \"3.7\""}
 idna = "*"
 outcome = "*"
 sniffio = "*"
 sortedcontainers = "*"
 
-[package.dependencies.contextvars]
-python = "<3.7"
-version = ">=2.1"
-
 [[package]]
+name = "typing-extensions"
+version = "3.7.4.3"
+description = "Backported and Experimental Type Hints for Python 3.5+"
 category = "main"
-description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = "*"
+
+[[package]]
 name = "urllib3"
+version = "1.26.4"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
-version = "1.25.11"
 
 [package.extras]
-brotli = ["brotlipy (>=0.6.0)"]
 secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
-socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"]
+socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
+brotli = ["brotlipy (>=0.6.0)"]
 
 [[package]]
-category = "dev"
-description = "Virtual Python Environment builder"
 name = "virtualenv"
+version = "20.4.4"
+description = "Virtual Python Environment builder"
+category = "dev"
 optional = false
 python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
-version = "20.1.0"
 
 [package.dependencies]
 appdirs = ">=1.4.3,<2"
 distlib = ">=0.3.1,<1"
 filelock = ">=3.0.0,<4"
+importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
+importlib-resources = {version = ">=1.0", markers = "python_version < \"3.7\""}
 six = ">=1.9.0,<2"
 
-[package.dependencies.importlib-metadata]
-python = "<3.8"
-version = ">=0.12,<3"
-
-[package.dependencies.importlib-resources]
-python = "<3.7"
-version = ">=1.0"
-
 [package.extras]
 docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)"]
-testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "pytest-xdist (>=1.31.0)", "packaging (>=20.0)", "xonsh (>=0.9.16)"]
+testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)", "xonsh (>=0.9.16)"]
 
 [[package]]
-category = "main"
-description = "Library of web-related functions"
 name = "w3lib"
+version = "1.22.0"
+description = "Library of web-related functions"
+category = "main"
 optional = false
 python-versions = "*"
-version = "1.22.0"
 
 [package.dependencies]
 six = ">=1.4.1"
 
 [[package]]
-category = "dev"
-description = "Measures the displayed width of unicode strings in a terminal"
 name = "wcwidth"
+version = "0.2.5"
+description = "Measures the displayed width of unicode strings in a terminal"
+category = "dev"
 optional = false
 python-versions = "*"
-version = "0.2.5"
 
 [[package]]
-category = "dev"
-description = "Backport of pathlib-compatible object wrapper for zip files"
-marker = "python_version < \"3.8\""
 name = "zipp"
+version = "3.4.1"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+category = "dev"
 optional = false
 python-versions = ">=3.6"
-version = "3.4.0"
 
 [package.extras]
-docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
-testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"]
+docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
+testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"]
 
 [[package]]
-category = "main"
-description = "Very basic event publishing system"
 name = "zope.event"
+version = "4.5.0"
+description = "Very basic event publishing system"
+category = "main"
 optional = true
 python-versions = "*"
-version = "4.5.0"
-
-[package.dependencies]
-setuptools = "*"
 
 [package.extras]
 docs = ["sphinx"]
 test = ["zope.testrunner"]
 
 [[package]]
-category = "main"
-description = "Interfaces for Python"
 name = "zope.interface"
+version = "5.4.0"
+description = "Interfaces for Python"
+category = "main"
 optional = true
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "5.1.2"
-
-[package.dependencies]
-setuptools = "*"
 
 [package.extras]
 docs = ["sphinx", "repoze.sphinx.autointerface"]
@@ -1114,30 +1023,31 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
 
 [extras]
 full = ["gevent", "trio"]
-gevent = []
+gevent = ["gevent"]
 trio = ["trio"]
 
 [metadata]
-content-hash = "a4886bb79cb355dd38eabda20aa5655ebf26c4ac9f5c1ea70cd03407a28f9f27"
-python-versions = "^3.6"
+lock-version = "1.1"
+python-versions = "^3.6.2"
+content-hash = "51bfaa7b49e09c88bcdaada679b5cf3fae6fa896f0626c07881458137962f869"
 
 [metadata.files]
+anyio = [
+    { file = "anyio-3.0.1-py3-none-any.whl", hash = "sha256:ed71f7542ef39875b65def219794d9dcb0a48c571317b13612c12b1f292701b5" },
+    { file = "anyio-3.0.1.tar.gz", hash = "sha256:1ef7622396ab55829d4236a6f75e2199df6d26a4ba79bea0cb942a5fd2f79a23" },
+]
 appdirs = [
     {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
     {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
 ]
 argcomplete = [
-    {file = "argcomplete-1.12.1-py2.py3-none-any.whl", hash = "sha256:5cd1ac4fc49c29d6016fc2cc4b19a3c08c3624544503495bf25989834c443898"},
-    {file = "argcomplete-1.12.1.tar.gz", hash = "sha256:849c2444c35bb2175aea74100ca5f644c29bf716429399c0f2203bb5d9a8e4e6"},
+    { file = "argcomplete-1.12.3-py2.py3-none-any.whl", hash = "sha256:291f0beca7fd49ce285d2f10e4c1c77e9460cf823eef2de54df0c0fec88b0d81" },
+    { file = "argcomplete-1.12.3.tar.gz", hash = "sha256:2c7dbffd8c045ea534921e63b0be6fe65e88599990d8dc408ac8c542b72a5445" },
 ]
 async-generator = [
     {file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"},
     {file = "async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"},
 ]
-asynctest = [
-    {file = "asynctest-0.13.0-py3-none-any.whl", hash = "sha256:5da6118a7e6d6b54d83a8f7197769d046922a44d2a99c21382f0a6e4fadae676"},
-    {file = "asynctest-0.13.0.tar.gz", hash = "sha256:c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"},
-]
 atomicwrites = [
     {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
     {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
@@ -1147,71 +1057,72 @@ attrs = [
     {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"},
 ]
 bandit = [
-    {file = "bandit-1.6.2-py2.py3-none-any.whl", hash = "sha256:336620e220cf2d3115877685e264477ff9d9abaeb0afe3dc7264f55fa17a3952"},
-    {file = "bandit-1.6.2.tar.gz", hash = "sha256:41e75315853507aa145d62a78a2a6c5e3240fe14ee7c601459d0df9418196065"},
+    {file = "bandit-1.7.0-py3-none-any.whl", hash = "sha256:216be4d044209fa06cf2a3e51b319769a51be8318140659719aa7a115c35ed07"},
+    {file = "bandit-1.7.0.tar.gz", hash = "sha256:8a4c7415254d75df8ff3c3b15cfe9042ecee628a1e40b44c15a98890fbfc2608"},
 ]
 certifi = [
-    {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"},
-    {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"},
+    {file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"},
+    {file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"},
 ]
 cffi = [
-    {file = "cffi-1.14.3-2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3eeeb0405fd145e714f7633a5173318bd88d8bbfc3dd0a5751f8c4f70ae629bc"},
-    {file = "cffi-1.14.3-2-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:cb763ceceae04803adcc4e2d80d611ef201c73da32d8f2722e9d0ab0c7f10768"},
-    {file = "cffi-1.14.3-2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:44f60519595eaca110f248e5017363d751b12782a6f2bd6a7041cba275215f5d"},
-    {file = "cffi-1.14.3-2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c53af463f4a40de78c58b8b2710ade243c81cbca641e34debf3396a9640d6ec1"},
-    {file = "cffi-1.14.3-2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:33c6cdc071ba5cd6d96769c8969a0531be2d08c2628a0143a10a7dcffa9719ca"},
-    {file = "cffi-1.14.3-2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c11579638288e53fc94ad60022ff1b67865363e730ee41ad5e6f0a17188b327a"},
-    {file = "cffi-1.14.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:3cb3e1b9ec43256c4e0f8d2837267a70b0e1ca8c4f456685508ae6106b1f504c"},
-    {file = "cffi-1.14.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:f0620511387790860b249b9241c2f13c3a80e21a73e0b861a2df24e9d6f56730"},
-    {file = "cffi-1.14.3-cp27-cp27m-win32.whl", hash = "sha256:005f2bfe11b6745d726dbb07ace4d53f057de66e336ff92d61b8c7e9c8f4777d"},
-    {file = "cffi-1.14.3-cp27-cp27m-win_amd64.whl", hash = "sha256:2f9674623ca39c9ebe38afa3da402e9326c245f0f5ceff0623dccdac15023e05"},
-    {file = "cffi-1.14.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:09e96138280241bd355cd585148dec04dbbedb4f46128f340d696eaafc82dd7b"},
-    {file = "cffi-1.14.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:3363e77a6176afb8823b6e06db78c46dbc4c7813b00a41300a4873b6ba63b171"},
-    {file = "cffi-1.14.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:0ef488305fdce2580c8b2708f22d7785ae222d9825d3094ab073e22e93dfe51f"},
-    {file = "cffi-1.14.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:0b1ad452cc824665ddc682400b62c9e4f5b64736a2ba99110712fdee5f2505c4"},
-    {file = "cffi-1.14.3-cp35-cp35m-win32.whl", hash = "sha256:85ba797e1de5b48aa5a8427b6ba62cf69607c18c5d4eb747604b7302f1ec382d"},
-    {file = "cffi-1.14.3-cp35-cp35m-win_amd64.whl", hash = "sha256:e66399cf0fc07de4dce4f588fc25bfe84a6d1285cc544e67987d22663393926d"},
-    {file = "cffi-1.14.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:15f351bed09897fbda218e4db5a3d5c06328862f6198d4fb385f3e14e19decb3"},
-    {file = "cffi-1.14.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4d7c26bfc1ea9f92084a1d75e11999e97b62d63128bcc90c3624d07813c52808"},
-    {file = "cffi-1.14.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:23e5d2040367322824605bc29ae8ee9175200b92cb5483ac7d466927a9b3d537"},
-    {file = "cffi-1.14.3-cp36-cp36m-win32.whl", hash = "sha256:a624fae282e81ad2e4871bdb767e2c914d0539708c0f078b5b355258293c98b0"},
-    {file = "cffi-1.14.3-cp36-cp36m-win_amd64.whl", hash = "sha256:de31b5164d44ef4943db155b3e8e17929707cac1e5bd2f363e67a56e3af4af6e"},
-    {file = "cffi-1.14.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f92cdecb618e5fa4658aeb97d5eb3d2f47aa94ac6477c6daf0f306c5a3b9e6b1"},
-    {file = "cffi-1.14.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:22399ff4870fb4c7ef19fff6eeb20a8bbf15571913c181c78cb361024d574579"},
-    {file = "cffi-1.14.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:f4eae045e6ab2bb54ca279733fe4eb85f1effda392666308250714e01907f394"},
-    {file = "cffi-1.14.3-cp37-cp37m-win32.whl", hash = "sha256:b0358e6fefc74a16f745afa366acc89f979040e0cbc4eec55ab26ad1f6a9bfbc"},
-    {file = "cffi-1.14.3-cp37-cp37m-win_amd64.whl", hash = "sha256:6642f15ad963b5092d65aed022d033c77763515fdc07095208f15d3563003869"},
-    {file = "cffi-1.14.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:2791f68edc5749024b4722500e86303a10d342527e1e3bcac47f35fbd25b764e"},
-    {file = "cffi-1.14.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:529c4ed2e10437c205f38f3691a68be66c39197d01062618c55f74294a4a4828"},
-    {file = "cffi-1.14.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8f0f1e499e4000c4c347a124fa6a27d37608ced4fe9f7d45070563b7c4c370c9"},
-    {file = "cffi-1.14.3-cp38-cp38-win32.whl", hash = "sha256:3b8eaf915ddc0709779889c472e553f0d3e8b7bdf62dab764c8921b09bf94522"},
-    {file = "cffi-1.14.3-cp38-cp38-win_amd64.whl", hash = "sha256:bbd2f4dfee1079f76943767fce837ade3087b578aeb9f69aec7857d5bf25db15"},
-    {file = "cffi-1.14.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:cc75f58cdaf043fe6a7a6c04b3b5a0e694c6a9e24050967747251fb80d7bce0d"},
-    {file = "cffi-1.14.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:bf39a9e19ce7298f1bd6a9758fa99707e9e5b1ebe5e90f2c3913a47bc548747c"},
-    {file = "cffi-1.14.3-cp39-cp39-win32.whl", hash = "sha256:d80998ed59176e8cba74028762fbd9b9153b9afc71ea118e63bbf5d4d0f9552b"},
-    {file = "cffi-1.14.3-cp39-cp39-win_amd64.whl", hash = "sha256:c150eaa3dadbb2b5339675b88d4573c1be3cb6f2c33a6c83387e10cc0bf05bd3"},
-    {file = "cffi-1.14.3.tar.gz", hash = "sha256:f92f789e4f9241cd262ad7a555ca2c648a98178a953af117ef7fad46aa1d5591"},
+    {file = "cffi-1.14.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991"},
+    {file = "cffi-1.14.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1"},
+    {file = "cffi-1.14.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa"},
+    {file = "cffi-1.14.5-cp27-cp27m-win32.whl", hash = "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3"},
+    {file = "cffi-1.14.5-cp27-cp27m-win_amd64.whl", hash = "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5"},
+    {file = "cffi-1.14.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482"},
+    {file = "cffi-1.14.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6"},
+    {file = "cffi-1.14.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045"},
+    {file = "cffi-1.14.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa"},
+    {file = "cffi-1.14.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406"},
+    {file = "cffi-1.14.5-cp35-cp35m-win32.whl", hash = "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369"},
+    {file = "cffi-1.14.5-cp35-cp35m-win_amd64.whl", hash = "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315"},
+    {file = "cffi-1.14.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892"},
+    {file = "cffi-1.14.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058"},
+    {file = "cffi-1.14.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5"},
+    {file = "cffi-1.14.5-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132"},
+    {file = "cffi-1.14.5-cp36-cp36m-win32.whl", hash = "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53"},
+    {file = "cffi-1.14.5-cp36-cp36m-win_amd64.whl", hash = "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813"},
+    {file = "cffi-1.14.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73"},
+    {file = "cffi-1.14.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06"},
+    {file = "cffi-1.14.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1"},
+    {file = "cffi-1.14.5-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49"},
+    {file = "cffi-1.14.5-cp37-cp37m-win32.whl", hash = "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62"},
+    {file = "cffi-1.14.5-cp37-cp37m-win_amd64.whl", hash = "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4"},
+    {file = "cffi-1.14.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053"},
+    {file = "cffi-1.14.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0"},
+    {file = "cffi-1.14.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e"},
+    {file = "cffi-1.14.5-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827"},
+    {file = "cffi-1.14.5-cp38-cp38-win32.whl", hash = "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e"},
+    {file = "cffi-1.14.5-cp38-cp38-win_amd64.whl", hash = "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396"},
+    {file = "cffi-1.14.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea"},
+    {file = "cffi-1.14.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322"},
+    {file = "cffi-1.14.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c"},
+    {file = "cffi-1.14.5-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee"},
+    {file = "cffi-1.14.5-cp39-cp39-win32.whl", hash = "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396"},
+    {file = "cffi-1.14.5-cp39-cp39-win_amd64.whl", hash = "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d"},
+    {file = "cffi-1.14.5.tar.gz", hash = "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"},
 ]
 chardet = [
-    {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
-    {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"},
+    {file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"},
+    {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
 ]
 click = [
     {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
     {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
 ]
 codecov = [
-    {file = "codecov-2.1.10-py2.py3-none-any.whl", hash = "sha256:61bc71b5f58be8000bf9235aa9d0112f8fd3acca00aa02191bb81426d22a8584"},
-    {file = "codecov-2.1.10-py3.8.egg", hash = "sha256:a333626e6ff882db760ce71a1d84baf80ddff2cd459a3cc49b41fdac47d77ca5"},
-    {file = "codecov-2.1.10.tar.gz", hash = "sha256:d30ad6084501224b1ba699cbf018a340bb9553eb2701301c14133995fdd84f33"},
+    {file = "codecov-2.1.11-py2.py3-none-any.whl", hash = "sha256:ba8553a82942ce37d4da92b70ffd6d54cf635fc1793ab0a7dc3fecd6ebfb3df8"},
+    {file = "codecov-2.1.11-py3.8.egg", hash = "sha256:e95901d4350e99fc39c8353efa450050d2446c55bac91d90fcfd2354e19a6aef"},
+    {file = "codecov-2.1.11.tar.gz", hash = "sha256:6cde272454009d27355f9434f4e49f238c0273b216beda8472a65dc4957f473b"},
 ]
 colorama = [
     {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
     {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
 ]
 colorlog = [
-    {file = "colorlog-4.4.0-py2.py3-none-any.whl", hash = "sha256:f14f30f58e2ce6ef40b0088307cac7efb9ecff5605fa2267a2d29955f26aff23"},
-    {file = "colorlog-4.4.0.tar.gz", hash = "sha256:0272c537469ab1e63b9915535874d15b671963c9325db0c4891a2aeff97ce3d1"},
+    {file = "colorlog-4.8.0-py2.py3-none-any.whl", hash = "sha256:3dd15cb27e8119a24c1a7b5c93f9f3b455855e0f73993b1c25921b2f646f1dcd"},
+    {file = "colorlog-4.8.0.tar.gz", hash = "sha256:59b53160c60902c405cdec28d38356e09d40686659048893e026ecbd589516b1"},
 ]
 configuror = [
     {file = "configuror-0.2.0-py3-none-any.whl", hash = "sha256:661145619b7279b02a5ba5f6ae75bd6d144f1dc8a73fb782e39a846c338a732a"},
@@ -1221,53 +1132,71 @@ contextvars = [
     {file = "contextvars-2.4.tar.gz", hash = "sha256:f38c908aaa59c14335eeea12abea5f443646216c4e29380d7bf34d2018e2c39e"},
 ]
 coverage = [
-    {file = "coverage-5.3-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:bd3166bb3b111e76a4f8e2980fa1addf2920a4ca9b2b8ca36a3bc3dedc618270"},
-    {file = "coverage-5.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9342dd70a1e151684727c9c91ea003b2fb33523bf19385d4554f7897ca0141d4"},
-    {file = "coverage-5.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:63808c30b41f3bbf65e29f7280bf793c79f54fb807057de7e5238ffc7cc4d7b9"},
-    {file = "coverage-5.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4d6a42744139a7fa5b46a264874a781e8694bb32f1d76d8137b68138686f1729"},
-    {file = "coverage-5.3-cp27-cp27m-win32.whl", hash = "sha256:86e9f8cd4b0cdd57b4ae71a9c186717daa4c5a99f3238a8723f416256e0b064d"},
-    {file = "coverage-5.3-cp27-cp27m-win_amd64.whl", hash = "sha256:7858847f2d84bf6e64c7f66498e851c54de8ea06a6f96a32a1d192d846734418"},
-    {file = "coverage-5.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:530cc8aaf11cc2ac7430f3614b04645662ef20c348dce4167c22d99bec3480e9"},
-    {file = "coverage-5.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:381ead10b9b9af5f64646cd27107fb27b614ee7040bb1226f9c07ba96625cbb5"},
-    {file = "coverage-5.3-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:71b69bd716698fa62cd97137d6f2fdf49f534decb23a2c6fc80813e8b7be6822"},
-    {file = "coverage-5.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:1d44bb3a652fed01f1f2c10d5477956116e9b391320c94d36c6bf13b088a1097"},
-    {file = "coverage-5.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1c6703094c81fa55b816f5ae542c6ffc625fec769f22b053adb42ad712d086c9"},
-    {file = "coverage-5.3-cp35-cp35m-win32.whl", hash = "sha256:cedb2f9e1f990918ea061f28a0f0077a07702e3819602d3507e2ff98c8d20636"},
-    {file = "coverage-5.3-cp35-cp35m-win_amd64.whl", hash = "sha256:7f43286f13d91a34fadf61ae252a51a130223c52bfefb50310d5b2deb062cf0f"},
-    {file = "coverage-5.3-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:c851b35fc078389bc16b915a0a7c1d5923e12e2c5aeec58c52f4aa8085ac8237"},
-    {file = "coverage-5.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:aac1ba0a253e17889550ddb1b60a2063f7474155465577caa2a3b131224cfd54"},
-    {file = "coverage-5.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2b31f46bf7b31e6aa690d4c7a3d51bb262438c6dcb0d528adde446531d0d3bb7"},
-    {file = "coverage-5.3-cp36-cp36m-win32.whl", hash = "sha256:c5f17ad25d2c1286436761b462e22b5020d83316f8e8fcb5deb2b3151f8f1d3a"},
-    {file = "coverage-5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:aef72eae10b5e3116bac6957de1df4d75909fc76d1499a53fb6387434b6bcd8d"},
-    {file = "coverage-5.3-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:e8caf961e1b1a945db76f1b5fa9c91498d15f545ac0ababbe575cfab185d3bd8"},
-    {file = "coverage-5.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:29a6272fec10623fcbe158fdf9abc7a5fa032048ac1d8631f14b50fbfc10d17f"},
-    {file = "coverage-5.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2d43af2be93ffbad25dd959899b5b809618a496926146ce98ee0b23683f8c51c"},
-    {file = "coverage-5.3-cp37-cp37m-win32.whl", hash = "sha256:c3888a051226e676e383de03bf49eb633cd39fc829516e5334e69b8d81aae751"},
-    {file = "coverage-5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9669179786254a2e7e57f0ecf224e978471491d660aaca833f845b72a2df3709"},
-    {file = "coverage-5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0203acd33d2298e19b57451ebb0bed0ab0c602e5cf5a818591b4918b1f97d516"},
-    {file = "coverage-5.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:582ddfbe712025448206a5bc45855d16c2e491c2dd102ee9a2841418ac1c629f"},
-    {file = "coverage-5.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0f313707cdecd5cd3e217fc68c78a960b616604b559e9ea60cc16795c4304259"},
-    {file = "coverage-5.3-cp38-cp38-win32.whl", hash = "sha256:78e93cc3571fd928a39c0b26767c986188a4118edc67bc0695bc7a284da22e82"},
-    {file = "coverage-5.3-cp38-cp38-win_amd64.whl", hash = "sha256:8f264ba2701b8c9f815b272ad568d555ef98dfe1576802ab3149c3629a9f2221"},
-    {file = "coverage-5.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:50691e744714856f03a86df3e2bff847c2acede4c191f9a1da38f088df342978"},
-    {file = "coverage-5.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:9361de40701666b034c59ad9e317bae95c973b9ff92513dd0eced11c6adf2e21"},
-    {file = "coverage-5.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:c1b78fb9700fc961f53386ad2fd86d87091e06ede5d118b8a50dea285a071c24"},
-    {file = "coverage-5.3-cp39-cp39-win32.whl", hash = "sha256:cb7df71de0af56000115eafd000b867d1261f786b5eebd88a0ca6360cccfaca7"},
-    {file = "coverage-5.3-cp39-cp39-win_amd64.whl", hash = "sha256:47a11bdbd8ada9b7ee628596f9d97fbd3851bd9999d398e9436bd67376dbece7"},
-    {file = "coverage-5.3.tar.gz", hash = "sha256:280baa8ec489c4f542f8940f9c4c2181f0306a8ee1a54eceba071a449fb870a0"},
+    {file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"},
+    {file = "coverage-5.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b"},
+    {file = "coverage-5.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669"},
+    {file = "coverage-5.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90"},
+    {file = "coverage-5.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c"},
+    {file = "coverage-5.5-cp27-cp27m-win32.whl", hash = "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a"},
+    {file = "coverage-5.5-cp27-cp27m-win_amd64.whl", hash = "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82"},
+    {file = "coverage-5.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905"},
+    {file = "coverage-5.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083"},
+    {file = "coverage-5.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5"},
+    {file = "coverage-5.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81"},
+    {file = "coverage-5.5-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6"},
+    {file = "coverage-5.5-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0"},
+    {file = "coverage-5.5-cp310-cp310-win_amd64.whl", hash = "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae"},
+    {file = "coverage-5.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb"},
+    {file = "coverage-5.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160"},
+    {file = "coverage-5.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"},
+    {file = "coverage-5.5-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701"},
+    {file = "coverage-5.5-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793"},
+    {file = "coverage-5.5-cp35-cp35m-win32.whl", hash = "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e"},
+    {file = "coverage-5.5-cp35-cp35m-win_amd64.whl", hash = "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3"},
+    {file = "coverage-5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066"},
+    {file = "coverage-5.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a"},
+    {file = "coverage-5.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465"},
+    {file = "coverage-5.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb"},
+    {file = "coverage-5.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821"},
+    {file = "coverage-5.5-cp36-cp36m-win32.whl", hash = "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45"},
+    {file = "coverage-5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184"},
+    {file = "coverage-5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a"},
+    {file = "coverage-5.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53"},
+    {file = "coverage-5.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d"},
+    {file = "coverage-5.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638"},
+    {file = "coverage-5.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3"},
+    {file = "coverage-5.5-cp37-cp37m-win32.whl", hash = "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a"},
+    {file = "coverage-5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a"},
+    {file = "coverage-5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6"},
+    {file = "coverage-5.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2"},
+    {file = "coverage-5.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759"},
+    {file = "coverage-5.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873"},
+    {file = "coverage-5.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a"},
+    {file = "coverage-5.5-cp38-cp38-win32.whl", hash = "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6"},
+    {file = "coverage-5.5-cp38-cp38-win_amd64.whl", hash = "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502"},
+    {file = "coverage-5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b"},
+    {file = "coverage-5.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529"},
+    {file = "coverage-5.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b"},
+    {file = "coverage-5.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff"},
+    {file = "coverage-5.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b"},
+    {file = "coverage-5.5-cp39-cp39-win32.whl", hash = "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6"},
+    {file = "coverage-5.5-cp39-cp39-win_amd64.whl", hash = "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03"},
+    {file = "coverage-5.5-pp36-none-any.whl", hash = "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079"},
+    {file = "coverage-5.5-pp37-none-any.whl", hash = "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4"},
+    {file = "coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c"},
 ]
 cssselect = [
     {file = "cssselect-1.1.0-py2.py3-none-any.whl", hash = "sha256:f612ee47b749c877ebae5bb77035d8f4202c6ad0f0fc1271b3c18ad6c4468ecf"},
     {file = "cssselect-1.1.0.tar.gz", hash = "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc"},
 ]
+dataclasses = [
+    {file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"},
+    {file = "dataclasses-0.8.tar.gz", hash = "sha256:8479067f342acf957dc82ec415d355ab5edb7e7646b90dc6e2fd1d96ad084c97"},
+]
 distlib = [
     {file = "distlib-0.3.1-py2.py3-none-any.whl", hash = "sha256:8c09de2c67b3e7deef7184574fc060ab8a793e7adbb183d942c389c8b13c52fb"},
     {file = "distlib-0.3.1.zip", hash = "sha256:edf6116872c863e1aa9d5bb7cb5e05a022c519a4594dc703843343a9ddd9bff1"},
 ]
-dnspython = [
-    {file = "dnspython-1.16.0-py2.py3-none-any.whl", hash = "sha256:f69c21288a962f4da86e56c4905b49d11aba7938d3d740e80d9e366ee4f1632d"},
-    {file = "dnspython-1.16.0.zip", hash = "sha256:36c5e8e38d4369a08b6780b7f27d790a292b2b08eea01607865bf0936c558e01"},
-]
 fake-useragent = [
     {file = "fake-useragent-0.1.11.tar.gz", hash = "sha256:c104998b750eb097eefc28ae28e92d66397598d2cf41a31aa45d5559ef1adf35"},
 ]
@@ -1276,123 +1205,139 @@ filelock = [
     {file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"},
 ]
 flake8 = [
-    {file = "flake8-3.8.4-py2.py3-none-any.whl", hash = "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839"},
-    {file = "flake8-3.8.4.tar.gz", hash = "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"},
+    { file = "flake8-3.9.1-py2.py3-none-any.whl", hash = "sha256:3b9f848952dddccf635be78098ca75010f073bfe14d2c6bda867154bea728d2a" },
+    { file = "flake8-3.9.1.tar.gz", hash = "sha256:1aa8990be1e689d96c745c5682b687ea49f2e05a443aff1f8251092b0014e378" },
 ]
 future = [
     {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"},
 ]
 gevent = [
-    {file = "gevent-20.9.0-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:1628a403fc9c3ea9b35924638a4d4fbe236f60ecdf4e22ed133fbbaf0bc7cb6b"},
-    {file = "gevent-20.9.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:283a021a2e14adfad718346f18982b80569d9c3a59e97cfae1b7d4c5b017941a"},
-    {file = "gevent-20.9.0-cp27-cp27m-win32.whl", hash = "sha256:315a63a35068183dfb9bc0331c7bb3c265ee7db8a11797cbe98dadbdb45b5d35"},
-    {file = "gevent-20.9.0-cp27-cp27m-win_amd64.whl", hash = "sha256:324808a8558c733f7a9734525483795d52ca3bbd5662b24b361d81c075414b1f"},
-    {file = "gevent-20.9.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:2aa70726ad1883fe7c17774e5ccc91ac6e30334efa29bafb9b8fe8ca6091b219"},
-    {file = "gevent-20.9.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:dd4c6b2f540b25c3d0f277a725bc1a900ce30a681b90a081216e31f814be453b"},
-    {file = "gevent-20.9.0-cp35-cp35m-win32.whl", hash = "sha256:1cfa3674866294623e324fa5b76eba7b96744d1956a605cfe24d26c5cd890f91"},
-    {file = "gevent-20.9.0-cp35-cp35m-win_amd64.whl", hash = "sha256:906175e3fb25f377a0b581e79d3ed5a7d925c136ff92fd022bb3013e25f5f3a9"},
-    {file = "gevent-20.9.0-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:fb33dc1ab27557bccd64ad4bf81e68c8b0d780fe937b1e2c0814558798137229"},
-    {file = "gevent-20.9.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:eba19bae532d0c48d489fa16815b242ce074b1f4b63e8a8e663232cbe311ead9"},
-    {file = "gevent-20.9.0-cp36-cp36m-win32.whl", hash = "sha256:db208e74a32cff7f55f5aa1ba5d7d1c1a086a6325c8702ae78a5c741155552ff"},
-    {file = "gevent-20.9.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2269574444113cb4ca1c1808ab9460a87fe25e1c34a6e36d975d4af46e4afff9"},
-    {file = "gevent-20.9.0-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:adbb267067f56696b2babced3d0856aa39dcf14b8ccd2dffa1fab587b00c6f80"},
-    {file = "gevent-20.9.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:9bb477f514cf39dc20651b479bf1ad4f38b9a679be2bfa3e162ec0c3785dfa2a"},
-    {file = "gevent-20.9.0-cp37-cp37m-win32.whl", hash = "sha256:10110d4881aec04f218c316cb796b18c8b2cac67ae0eb5b0c5780056757268a2"},
-    {file = "gevent-20.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e11de4b4d107ca2f35000eb08e9c4c4621c153103b400f48a9ea95b96d8c7e0b"},
-    {file = "gevent-20.9.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:a8733a01974433d91308f8c44fa6cc13428b15bb39d46540657e260ff8852cb1"},
-    {file = "gevent-20.9.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:afc177c37de41ce9c27d351ac84cbaf34407effcab5d6641645838f39d365be1"},
-    {file = "gevent-20.9.0-cp38-cp38-win32.whl", hash = "sha256:93980e51dd2e5f81899d644a0b6ef4a73008c679fcedd50e3b21cc3451ba2424"},
-    {file = "gevent-20.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:b2948566003a1030e47507755fe1f446995e8671c0c67571091539e01faf94cc"},
-    {file = "gevent-20.9.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:b07fcbca3e819296979d82fac3d8b44f0d5ced57b9a04dffcfd194da99c8eb2d"},
-    {file = "gevent-20.9.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:33a63f230755c6813fca39d9cea2a8894df32df2ee58fd69d8bf8fcc1d8e018e"},
-    {file = "gevent-20.9.0-pp27-pypy_73-win32.whl", hash = "sha256:8d338cd6d040fe2607e5305dd7991b5960b3780ae01f804c2ac5760d31d3b2c6"},
-    {file = "gevent-20.9.0.tar.gz", hash = "sha256:5f6d48051d336561ec08995431ee4d265ac723a64bba99cc58c3eb1a4d4f5c8d"},
+    {file = "gevent-20.12.1-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:0f9fa230c5878704b9e286ad5038bac3b70d293bf10e9efa8b2ae1d7d80e7e08"},
+    {file = "gevent-20.12.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f020bfb34d57caa10029111be776524c378a4aac8417bc6fb1154b05e00fc220"},
+    {file = "gevent-20.12.1-cp27-cp27m-win32.whl", hash = "sha256:e233ae153b586b61e492806d4cd1be2217de7441922c02053b67de14800bce96"},
+    {file = "gevent-20.12.1-cp27-cp27m-win_amd64.whl", hash = "sha256:2d05f38a5ef1ebb7ceb692897674b11ba603914524765b989c65c020c7b08360"},
+    {file = "gevent-20.12.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ffa1be13963db6aa55c50d2fd4a656c82f53a03a47e37aaa69e79a488123538d"},
+    {file = "gevent-20.12.1-cp35-cp35m-win32.whl", hash = "sha256:caec00914e8f21b2c77a29bbc2ef3abfeadf7515656e5451dfb14c2064733998"},
+    {file = "gevent-20.12.1-cp35-cp35m-win_amd64.whl", hash = "sha256:19bd3fe60dec45fe6420b7772496950215f1b36701905876ba1644b6b2064163"},
+    {file = "gevent-20.12.1-cp36-cp36m-win32.whl", hash = "sha256:9d001fc899db6e140110ae7484e58cd74b0dfa5cee021a0347f00bb441ac78bd"},
+    {file = "gevent-20.12.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b57586ad3fedf13d351d2559b70d6fe593c50400315d52bb3c072285da60fa37"},
+    {file = "gevent-20.12.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:69ddc1767a02f68e71d5e0d3215aa4d28872187715627f71ff0eadd7b7a5e7f4"},
+    {file = "gevent-20.12.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:89c583744f91052ae987356660f5ed0b8fc59a1230b051d6ccc10d37a155fe01"},
+    {file = "gevent-20.12.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:f3faf1834464f1b0731aa6346cd9f41029fa9e208d6ecbce4a736c19562c86aa"},
+    {file = "gevent-20.12.1-cp37-cp37m-win32.whl", hash = "sha256:4baecba0fd614e14dc1f3f8c35616cb248cdb893de576150ed1fc7fc66b8ba3d"},
+    {file = "gevent-20.12.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4b0a5626c4e534d184cdf00d66f06de3885beafaaa5f7b98d47186ea175629a1"},
+    {file = "gevent-20.12.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:81e38ed46e21e0b00b930efce1a1ff46c7722ad83d84052f71a757f23cbed1c0"},
+    {file = "gevent-20.12.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:895c76a89907d9d37fdfaf5321cb0fff0cba396f003bedb4f5fc13836da6f250"},
+    {file = "gevent-20.12.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:c3706a620e167c4bd007f16f113928324c4e07a7bae11d6d18d65f82abcd7a58"},
+    {file = "gevent-20.12.1-cp38-cp38-win32.whl", hash = "sha256:ba244028225ff8d3a58f344fcd16ab05b0e3642b34d81f51f7fa3c70761f6c34"},
+    {file = "gevent-20.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c570a2e3100f758a5c2f9b993ecf870ee784390e44e1a292c361d6b32fb3ad4c"},
+    {file = "gevent-20.12.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:f857adbe1bf41e620d86173a53100f4ec328eba3089069a4815b3d9f4229dee8"},
+    {file = "gevent-20.12.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:bf946a99e364ebcc95b82c794d5d1a67f13115adbefab7b9e12791f13184cfd5"},
+    {file = "gevent-20.12.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:60799fd7dcbb622f8435eb12436d48a8d27f8e7b3d23631e32ccc04ddd2097c2"},
+    {file = "gevent-20.12.1-pp27-pypy_73-win32.whl", hash = "sha256:7a808c63f065a303bbbe87c5c0754e06abb1e23e18752f418dce1eb3189cb43d"},
+    {file = "gevent-20.12.1.tar.gz", hash = "sha256:99b68765767bb3e2244a66b012883899a6f17c23b6dc1cd80b793df341e15f08"},
 ]
 gitdb = [
-    {file = "gitdb-4.0.5-py3-none-any.whl", hash = "sha256:91f36bfb1ab7949b3b40e23736db18231bf7593edada2ba5c3a174a7b23657ac"},
-    {file = "gitdb-4.0.5.tar.gz", hash = "sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9"},
+    { file = "gitdb-4.0.7-py3-none-any.whl", hash = "sha256:6c4cc71933456991da20917998acbe6cf4fb41eeaab7d6d67fbc05ecd4c865b0" },
+    { file = "gitdb-4.0.7.tar.gz", hash = "sha256:96bf5c08b157a666fec41129e6d327235284cca4c81e92109260f353ba138005" },
 ]
 gitpython = [
-    {file = "GitPython-3.1.11-py3-none-any.whl", hash = "sha256:6eea89b655917b500437e9668e4a12eabdcf00229a0df1762aabd692ef9b746b"},
-    {file = "GitPython-3.1.11.tar.gz", hash = "sha256:befa4d101f91bad1b632df4308ec64555db684c360bd7d2130b4807d49ce86b8"},
+    { file = "GitPython-3.1.15-py3-none-any.whl", hash = "sha256:a77824e516d3298b04fb36ec7845e92747df8fcfee9cacc32dd6239f9652f867" },
+    { file = "GitPython-3.1.15.tar.gz", hash = "sha256:05af150f47a5cca3f4b0af289b73aef8cf3c4fe2385015b06220cbcdee48bb6e" },
 ]
 greenlet = [
-    {file = "greenlet-0.4.17-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:75e4c27188f28149b74e7685809f9227410fd15432a4438fc48627f518577fa5"},
-    {file = "greenlet-0.4.17-cp27-cp27m-win32.whl", hash = "sha256:3af587e9813f9bd8be9212722321a5e7be23b2bc37e6323a90e592ab0c2ef117"},
-    {file = "greenlet-0.4.17-cp27-cp27m-win_amd64.whl", hash = "sha256:ccd62f09f90b2730150d82f2f2ffc34d73c6ce7eac234aed04d15dc8a3023994"},
-    {file = "greenlet-0.4.17-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:13037e2d7ab2145300676852fa069235512fdeba4ed1e3bb4b0677a04223c525"},
-    {file = "greenlet-0.4.17-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:e495096e3e2e8f7192afb6aaeba19babc4fb2bdf543d7b7fed59e00c1df7f170"},
-    {file = "greenlet-0.4.17-cp35-cp35m-win32.whl", hash = "sha256:124a3ae41215f71dc91d1a3d45cbf2f84e46b543e5d60b99ecc20e24b4c8f272"},
-    {file = "greenlet-0.4.17-cp35-cp35m-win_amd64.whl", hash = "sha256:5494e3baeacc371d988345fbf8aa4bd15555b3077c40afcf1994776bb6d77eaf"},
-    {file = "greenlet-0.4.17-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bee111161420f341a346731279dd976be161b465c1286f82cc0779baf7b729e8"},
-    {file = "greenlet-0.4.17-cp36-cp36m-win32.whl", hash = "sha256:ac85db59aa43d78547f95fc7b6fd2913e02b9e9b09e2490dfb7bbdf47b2a4914"},
-    {file = "greenlet-0.4.17-cp36-cp36m-win_amd64.whl", hash = "sha256:4481002118b2f1588fa3d821936ffdc03db80ef21186b62b90c18db4ba5e743b"},
-    {file = "greenlet-0.4.17-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:be7a79988b8fdc5bbbeaed69e79cfb373da9759242f1565668be4fb7f3f37552"},
-    {file = "greenlet-0.4.17-cp37-cp37m-win32.whl", hash = "sha256:97f2b01ab622a4aa4b3724a3e1fba66f47f054c434fbaa551833fa2b41e3db51"},
-    {file = "greenlet-0.4.17-cp37-cp37m-win_amd64.whl", hash = "sha256:d3436110ca66fe3981031cc6aff8cc7a40d8411d173dde73ddaa5b8445385e2d"},
-    {file = "greenlet-0.4.17-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:a34023b9eabb3525ee059f3bf33a417d2e437f7f17e341d334987d4091ae6072"},
-    {file = "greenlet-0.4.17-cp38-cp38-win32.whl", hash = "sha256:e66a824f44892bc4ec66c58601a413419cafa9cec895e63d8da889c8a1a4fa4a"},
-    {file = "greenlet-0.4.17-cp38-cp38-win_amd64.whl", hash = "sha256:47825c3a109f0331b1e54c1173d4e57fa000aa6c96756b62852bfa1af91cd652"},
-    {file = "greenlet-0.4.17-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1023d7b43ca11264ab7052cb09f5635d4afdb43df55e0854498fc63070a0b206"},
-    {file = "greenlet-0.4.17.tar.gz", hash = "sha256:41d8835c69a78de718e466dd0e6bfd4b46125f21a67c3ff6d76d8d8059868d6b"},
+    {file = "greenlet-1.0.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:1d1d4473ecb1c1d31ce8fd8d91e4da1b1f64d425c1dc965edc4ed2a63cfa67b2"},
+    {file = "greenlet-1.0.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:cfd06e0f0cc8db2a854137bd79154b61ecd940dce96fad0cba23fe31de0b793c"},
+    {file = "greenlet-1.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:eb333b90036358a0e2c57373f72e7648d7207b76ef0bd00a4f7daad1f79f5203"},
+    {file = "greenlet-1.0.0-cp27-cp27m-win32.whl", hash = "sha256:1a1ada42a1fd2607d232ae11a7b3195735edaa49ea787a6d9e6a53afaf6f3476"},
+    {file = "greenlet-1.0.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f6f65bf54215e4ebf6b01e4bb94c49180a589573df643735107056f7a910275b"},
+    {file = "greenlet-1.0.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:f59eded163d9752fd49978e0bab7a1ff21b1b8d25c05f0995d140cc08ac83379"},
+    {file = "greenlet-1.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:875d4c60a6299f55df1c3bb870ebe6dcb7db28c165ab9ea6cdc5d5af36bb33ce"},
+    {file = "greenlet-1.0.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:1bb80c71de788b36cefb0c3bb6bfab306ba75073dbde2829c858dc3ad70f867c"},
+    {file = "greenlet-1.0.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b5f1b333015d53d4b381745f5de842f19fe59728b65f0fbb662dafbe2018c3a5"},
+    {file = "greenlet-1.0.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:5352c15c1d91d22902582e891f27728d8dac3bd5e0ee565b6a9f575355e6d92f"},
+    {file = "greenlet-1.0.0-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:2c65320774a8cd5fdb6e117c13afa91c4707548282464a18cf80243cf976b3e6"},
+    {file = "greenlet-1.0.0-cp35-cp35m-manylinux2014_ppc64le.whl", hash = "sha256:111cfd92d78f2af0bc7317452bd93a477128af6327332ebf3c2be7df99566683"},
+    {file = "greenlet-1.0.0-cp35-cp35m-win32.whl", hash = "sha256:cdb90267650c1edb54459cdb51dab865f6c6594c3a47ebd441bc493360c7af70"},
+    {file = "greenlet-1.0.0-cp35-cp35m-win_amd64.whl", hash = "sha256:eac8803c9ad1817ce3d8d15d1bb82c2da3feda6bee1153eec5c58fa6e5d3f770"},
+    {file = "greenlet-1.0.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:c93d1a71c3fe222308939b2e516c07f35a849c5047f0197442a4d6fbcb4128ee"},
+    {file = "greenlet-1.0.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:122c63ba795fdba4fc19c744df6277d9cfd913ed53d1a286f12189a0265316dd"},
+    {file = "greenlet-1.0.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:c5b22b31c947ad8b6964d4ed66776bcae986f73669ba50620162ba7c832a6b6a"},
+    {file = "greenlet-1.0.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:4365eccd68e72564c776418c53ce3c5af402bc526fe0653722bc89efd85bf12d"},
+    {file = "greenlet-1.0.0-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:da7d09ad0f24270b20f77d56934e196e982af0d0a2446120cb772be4e060e1a2"},
+    {file = "greenlet-1.0.0-cp36-cp36m-win32.whl", hash = "sha256:647ba1df86d025f5a34043451d7c4a9f05f240bee06277a524daad11f997d1e7"},
+    {file = "greenlet-1.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:e6e9fdaf6c90d02b95e6b0709aeb1aba5affbbb9ccaea5502f8638e4323206be"},
+    {file = "greenlet-1.0.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:62afad6e5fd70f34d773ffcbb7c22657e1d46d7fd7c95a43361de979f0a45aef"},
+    {file = "greenlet-1.0.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d3789c1c394944084b5e57c192889985a9f23bd985f6d15728c745d380318128"},
+    {file = "greenlet-1.0.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:f5e2d36c86c7b03c94b8459c3bd2c9fe2c7dab4b258b8885617d44a22e453fb7"},
+    {file = "greenlet-1.0.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:292e801fcb3a0b3a12d8c603c7cf340659ea27fd73c98683e75800d9fd8f704c"},
+    {file = "greenlet-1.0.0-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:f3dc68272990849132d6698f7dc6df2ab62a88b0d36e54702a8fd16c0490e44f"},
+    {file = "greenlet-1.0.0-cp37-cp37m-win32.whl", hash = "sha256:7cd5a237f241f2764324396e06298b5dee0df580cf06ef4ada0ff9bff851286c"},
+    {file = "greenlet-1.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:0ddd77586553e3daf439aa88b6642c5f252f7ef79a39271c25b1d4bf1b7cbb85"},
+    {file = "greenlet-1.0.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:90b6a25841488cf2cb1c8623a53e6879573010a669455046df5f029d93db51b7"},
+    {file = "greenlet-1.0.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ed1d1351f05e795a527abc04a0d82e9aecd3bdf9f46662c36ff47b0b00ecaf06"},
+    {file = "greenlet-1.0.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:94620ed996a7632723a424bccb84b07e7b861ab7bb06a5aeb041c111dd723d36"},
+    {file = "greenlet-1.0.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:f97d83049715fd9dec7911860ecf0e17b48d8725de01e45de07d8ac0bd5bc378"},
+    {file = "greenlet-1.0.0-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:0a77691f0080c9da8dfc81e23f4e3cffa5accf0f5b56478951016d7cfead9196"},
+    {file = "greenlet-1.0.0-cp38-cp38-win32.whl", hash = "sha256:e1128e022d8dce375362e063754e129750323b67454cac5600008aad9f54139e"},
+    {file = "greenlet-1.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d4030b04061fdf4cbc446008e238e44936d77a04b2b32f804688ad64197953c"},
+    {file = "greenlet-1.0.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:f8450d5ef759dbe59f84f2c9f77491bb3d3c44bc1a573746daf086e70b14c243"},
+    {file = "greenlet-1.0.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:df8053867c831b2643b2c489fe1d62049a98566b1646b194cc815f13e27b90df"},
+    {file = "greenlet-1.0.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:df3e83323268594fa9755480a442cabfe8d82b21aba815a71acf1bb6c1776218"},
+    {file = "greenlet-1.0.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:181300f826625b7fd1182205b830642926f52bd8cdb08b34574c9d5b2b1813f7"},
+    {file = "greenlet-1.0.0-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:58ca0f078d1c135ecf1879d50711f925ee238fe773dfe44e206d7d126f5bc664"},
+    {file = "greenlet-1.0.0-cp39-cp39-win32.whl", hash = "sha256:5f297cb343114b33a13755032ecf7109b07b9a0020e841d1c3cedff6602cc139"},
+    {file = "greenlet-1.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:5d69bbd9547d3bc49f8a545db7a0bd69f407badd2ff0f6e1a163680b5841d2b0"},
+    {file = "greenlet-1.0.0.tar.gz", hash = "sha256:719e169c79255816cdcf6dccd9ed2d089a72a9f6c42273aae12d55e8d35bdcf8"},
 ]
 h11 = [
-    {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"},
-    {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"},
-]
-h2 = [
-    {file = "h2-3.2.0-py2.py3-none-any.whl", hash = "sha256:61e0f6601fa709f35cdb730863b4e5ec7ad449792add80d1410d4174ed139af5"},
-    {file = "h2-3.2.0.tar.gz", hash = "sha256:875f41ebd6f2c44781259005b157faed1a5031df3ae5aa7bcb4628a6c0782f14"},
-]
-hpack = [
-    {file = "hpack-3.0.0-py2.py3-none-any.whl", hash = "sha256:0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89"},
-    {file = "hpack-3.0.0.tar.gz", hash = "sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2"},
+    {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"},
+    {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"},
 ]
-hstspreload = [
-    {file = "hstspreload-2020.10.20-py3-none-any.whl", hash = "sha256:0cd540f86c2930fe466348bd984e5ae1c96a0041fb97df61431997523d9e719d"},
-    {file = "hstspreload-2020.10.20.tar.gz", hash = "sha256:0a79313c2f52f18aa0ade1f27664ee39bee1cb4eb2ed1d610e2bd22e2e4050e1"},
+httpcore = [
+    {file = "httpcore-0.12.3-py3-none-any.whl", hash = "sha256:93e822cd16c32016b414b789aeff4e855d0ccbfc51df563ee34d4dbadbb3bcdc"},
+    {file = "httpcore-0.12.3.tar.gz", hash = "sha256:37ae835fb370049b2030c3290e12ed298bf1473c41bb72ca4aa78681eba9b7c9"},
 ]
 httpx = [
-    {file = "httpx-0.12.1-py3-none-any.whl", hash = "sha256:ce51c8e8ed2834447fde5a94650299fd74017b7da69cc786b6421fefda09a393"},
-    {file = "httpx-0.12.1.tar.gz", hash = "sha256:405b4749f597b1f45cae5bffc17b23dc251cce30a0c4c8126f1007b9e728a615"},
-]
-hyperframe = [
-    {file = "hyperframe-5.2.0-py2.py3-none-any.whl", hash = "sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40"},
-    {file = "hyperframe-5.2.0.tar.gz", hash = "sha256:a9f5c17f2cc3c719b917c4f33ed1c61bd1f8dfac4b1bd23b7c80b3400971b41f"},
+    {file = "httpx-0.17.1-py3-none-any.whl", hash = "sha256:d379653bd457e8257eb0df99cb94557e4aac441b7ba948e333be969298cac272"},
+    {file = "httpx-0.17.1.tar.gz", hash = "sha256:cc2a55188e4b25272d2bcd46379d300f632045de4377682aa98a8a6069d55967"},
 ]
 idna = [
     {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
     {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
 ]
 immutables = [
-    {file = "immutables-0.14-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:860666fab142401a5535bf65cbd607b46bc5ed25b9d1eb053ca8ed9a1a1a80d6"},
-    {file = "immutables-0.14-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:ce01788878827c3f0331c254a4ad8d9721489a5e65cc43e19c80040b46e0d297"},
-    {file = "immutables-0.14-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:8797eed4042f4626b0bc04d9cf134208918eb0c937a8193a2c66df5041e62d2e"},
-    {file = "immutables-0.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:33ce2f977da7b5e0dddd93744862404bdb316ffe5853ec853e53141508fa2e6a"},
-    {file = "immutables-0.14-cp36-cp36m-win_amd64.whl", hash = "sha256:6c8eace4d98988c72bcb37c05e79aae756832738305ae9497670482a82db08bc"},
-    {file = "immutables-0.14-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:ab6c18b7b2b2abc83e0edc57b0a38bf0915b271582a1eb8c7bed1c20398f8040"},
-    {file = "immutables-0.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c099212fd6504513a50e7369fe281007c820cf9d7bb22a336486c63d77d6f0b2"},
-    {file = "immutables-0.14-cp37-cp37m-win_amd64.whl", hash = "sha256:714aedbdeba4439d91cb5e5735cb10631fc47a7a69ea9cc8ecbac90322d50a4a"},
-    {file = "immutables-0.14-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:1c11050c49e193a1ec9dda1747285333f6ba6a30bbeb2929000b9b1192097ec0"},
-    {file = "immutables-0.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c453e12b95e1d6bb4909e8743f88b7f5c0c97b86a8bc0d73507091cb644e3c1e"},
-    {file = "immutables-0.14-cp38-cp38-win_amd64.whl", hash = "sha256:ef9da20ec0f1c5853b5c8f8e3d9e1e15b8d98c259de4b7515d789a606af8745e"},
-    {file = "immutables-0.14.tar.gz", hash = "sha256:a0a1cc238b678455145bae291d8426f732f5255537ed6a5b7645949704c70a78"},
+    {file = "immutables-0.15-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:6728f4392e3e8e64b593a5a0cd910a1278f07f879795517e09f308daed138631"},
+    {file = "immutables-0.15-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f0836cd3bdc37c8a77b192bbe5f41dbcc3ce654db048ebbba89bdfe6db7a1c7a"},
+    {file = "immutables-0.15-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:8703d8abfd8687932f2a05f38e7de270c3a6ca3bd1c1efb3c938656b3f2f985a"},
+    {file = "immutables-0.15-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:b8ad986f9b532c026f19585289384b0769188fcb68b37c7f0bd0df9092a6ca54"},
+    {file = "immutables-0.15-cp36-cp36m-win_amd64.whl", hash = "sha256:6f117d9206165b9dab8fd81c5129db757d1a044953f438654236ed9a7a4224ae"},
+    {file = "immutables-0.15-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:b75ade826920c4e490b1bb14cf967ac14e61eb7c5562161c5d7337d61962c226"},
+    {file = "immutables-0.15-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:b7e13c061785e34f73c4f659861f1b3e4a5fd918e4395c84b21c4e3d449ebe27"},
+    {file = "immutables-0.15-cp37-cp37m-win_amd64.whl", hash = "sha256:3035849accee4f4e510ed7c94366a40e0f5fef9069fbe04a35f4787b13610a4a"},
+    {file = "immutables-0.15-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:b04fa69174e0c8f815f9c55f2a43fc9e5a68452fab459a08e904a74e8471639f"},
+    {file = "immutables-0.15-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:141c2e9ea515a3a815007a429f0b47a578ebeb42c831edaec882a245a35fffca"},
+    {file = "immutables-0.15-cp38-cp38-win_amd64.whl", hash = "sha256:cbe8c64640637faa5535d539421b293327f119c31507c33ca880bd4f16035eb6"},
+    {file = "immutables-0.15-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:a0a4e4417d5ef4812d7f99470cd39347b58cb927365dd2b8da9161040d260db0"},
+    {file = "immutables-0.15-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3b15c08c71c59e5b7c2470ef949d49ff9f4263bb77f488422eaa157da84d6999"},
+    {file = "immutables-0.15-cp39-cp39-win_amd64.whl", hash = "sha256:2283a93c151566e6830aee0e5bee55fc273455503b43aa004356b50f9182092b"},
+    {file = "immutables-0.15.tar.gz", hash = "sha256:3713ab1ebbb6946b7ce1387bb9d1d7f5e09c45add58c2a2ee65f963c171e746b"},
 ]
 importlib-metadata = [
-    {file = "importlib_metadata-2.0.0-py2.py3-none-any.whl", hash = "sha256:cefa1a2f919b866c5beb7c9f7b0ebb4061f30a8a9bf16d609b000e2dfaceb9c3"},
-    {file = "importlib_metadata-2.0.0.tar.gz", hash = "sha256:77a540690e24b0305878c37ffd421785a6f7e53c8b5720d211b211de8d0e95da"},
+    { file = "importlib_metadata-4.0.1-py3-none-any.whl", hash = "sha256:d7eb1dea6d6a6086f8be21784cc9e3bcfa55872b52309bc5fad53a8ea444465d" },
+    { file = "importlib_metadata-4.0.1.tar.gz", hash = "sha256:8c501196e49fb9df5df43833bdb1e4328f64847763ec8a50703148b73784d581" },
 ]
 importlib-resources = [
-    {file = "importlib_resources-3.3.0-py2.py3-none-any.whl", hash = "sha256:a3d34a8464ce1d5d7c92b0ea4e921e696d86f2aa212e684451cb1482c8d84ed5"},
-    {file = "importlib_resources-3.3.0.tar.gz", hash = "sha256:7b51f0106c8ec564b1bef3d9c588bc694ce2b92125bbb6278f4f2f5b54ec3592"},
+    {file = "importlib_resources-5.1.2-py3-none-any.whl", hash = "sha256:ebab3efe74d83b04d6bf5cd9a17f0c5c93e60fb60f30c90f56265fce4682a469"},
+    {file = "importlib_resources-5.1.2.tar.gz", hash = "sha256:642586fc4740bd1cad7690f836b3321309402b20b332529f25617ff18e8e1370"},
 ]
 jinja2 = [
-    {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"},
-    {file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"},
+    {file = "Jinja2-2.11.3-py2.py3-none-any.whl", hash = "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419"},
+    {file = "Jinja2-2.11.3.tar.gz", hash = "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"},
 ]
 joblib = [
-    {file = "joblib-0.17.0-py3-none-any.whl", hash = "sha256:698c311779f347cf6b7e6b8a39bb682277b8ee4aba8cf9507bc0cf4cd4737b72"},
-    {file = "joblib-0.17.0.tar.gz", hash = "sha256:9e284edd6be6b71883a63c9b7f124738a3c16195513ad940eae7e3438de885d5"},
+    {file = "joblib-1.0.1-py3-none-any.whl", hash = "sha256:feeb1ec69c4d45129954f1b7034954241eedfd6ba39b5e9e4b6883be3332d5e5"},
+    {file = "joblib-1.0.1.tar.gz", hash = "sha256:9c17567692206d2f3fb9ecf5e991084254fe631665c450b443761c4186a613f7"},
 ]
 livereload = [
     {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"},
@@ -1402,46 +1347,46 @@ lunr = [
     {file = "lunr-0.5.8.tar.gz", hash = "sha256:c4fb063b98eff775dd638b3df380008ae85e6cb1d1a24d1cd81a10ef6391c26e"},
 ]
 lxml = [
-    {file = "lxml-4.6.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:4b7572145054330c8e324a72d808c8c8fbe12be33368db28c39a255ad5f7fb51"},
-    {file = "lxml-4.6.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:302160eb6e9764168e01d8c9ec6becddeb87776e81d3fcb0d97954dd51d48e0a"},
-    {file = "lxml-4.6.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d4ad7fd3269281cb471ad6c7bafca372e69789540d16e3755dd717e9e5c9d82f"},
-    {file = "lxml-4.6.1-cp27-cp27m-win32.whl", hash = "sha256:189ad47203e846a7a4951c17694d845b6ade7917c47c64b29b86526eefc3adf5"},
-    {file = "lxml-4.6.1-cp27-cp27m-win_amd64.whl", hash = "sha256:56eff8c6fb7bc4bcca395fdff494c52712b7a57486e4fbde34c31bb9da4c6cc4"},
-    {file = "lxml-4.6.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:23c83112b4dada0b75789d73f949dbb4e8f29a0a3511647024a398ebd023347b"},
-    {file = "lxml-4.6.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0e89f5d422988c65e6936e4ec0fe54d6f73f3128c80eb7ecc3b87f595523607b"},
-    {file = "lxml-4.6.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2358809cc64394617f2719147a58ae26dac9e21bae772b45cfb80baa26bfca5d"},
-    {file = "lxml-4.6.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:be1ebf9cc25ab5399501c9046a7dcdaa9e911802ed0e12b7d620cd4bbf0518b3"},
-    {file = "lxml-4.6.1-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:4fff34721b628cce9eb4538cf9a73d02e0f3da4f35a515773cce6f5fe413b360"},
-    {file = "lxml-4.6.1-cp35-cp35m-win32.whl", hash = "sha256:475325e037fdf068e0c2140b818518cf6bc4aa72435c407a798b2db9f8e90810"},
-    {file = "lxml-4.6.1-cp35-cp35m-win_amd64.whl", hash = "sha256:f98b6f256be6cec8dd308a8563976ddaff0bdc18b730720f6f4bee927ffe926f"},
-    {file = "lxml-4.6.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:be7c65e34d1b50ab7093b90427cbc488260e4b3a38ef2435d65b62e9fa3d798a"},
-    {file = "lxml-4.6.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:d18331ea905a41ae71596502bd4c9a2998902328bbabd29e3d0f5f8569fabad1"},
-    {file = "lxml-4.6.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3d9b2b72eb0dbbdb0e276403873ecfae870599c83ba22cadff2db58541e72856"},
-    {file = "lxml-4.6.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d20d32cbb31d731def4b1502294ca2ee99f9249b63bc80e03e67e8f8e126dea8"},
-    {file = "lxml-4.6.1-cp36-cp36m-win32.whl", hash = "sha256:d182eada8ea0de61a45a526aa0ae4bcd222f9673424e65315c35820291ff299c"},
-    {file = "lxml-4.6.1-cp36-cp36m-win_amd64.whl", hash = "sha256:c0dac835c1a22621ffa5e5f999d57359c790c52bbd1c687fe514ae6924f65ef5"},
-    {file = "lxml-4.6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d84d741c6e35c9f3e7406cb7c4c2e08474c2a6441d59322a00dcae65aac6315d"},
-    {file = "lxml-4.6.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:8862d1c2c020cb7a03b421a9a7b4fe046a208db30994fc8ff68c627a7915987f"},
-    {file = "lxml-4.6.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3a7a380bfecc551cfd67d6e8ad9faa91289173bdf12e9cfafbd2bdec0d7b1ec1"},
-    {file = "lxml-4.6.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:2d6571c48328be4304aee031d2d5046cbc8aed5740c654575613c5a4f5a11311"},
-    {file = "lxml-4.6.1-cp37-cp37m-win32.whl", hash = "sha256:803a80d72d1f693aa448566be46ffd70882d1ad8fc689a2e22afe63035eb998a"},
-    {file = "lxml-4.6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:24e811118aab6abe3ce23ff0d7d38932329c513f9cef849d3ee88b0f848f2aa9"},
-    {file = "lxml-4.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2e311a10f3e85250910a615fe194839a04a0f6bc4e8e5bb5cac221344e3a7891"},
-    {file = "lxml-4.6.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a71400b90b3599eb7bf241f947932e18a066907bf84617d80817998cee81e4bf"},
-    {file = "lxml-4.6.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:211b3bcf5da70c2d4b84d09232534ad1d78320762e2c59dedc73bf01cb1fc45b"},
-    {file = "lxml-4.6.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:e65c221b2115a91035b55a593b6eb94aa1206fa3ab374f47c6dc10d364583ff9"},
-    {file = "lxml-4.6.1-cp38-cp38-win32.whl", hash = "sha256:d6f8c23f65a4bfe4300b85f1f40f6c32569822d08901db3b6454ab785d9117cc"},
-    {file = "lxml-4.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:573b2f5496c7e9f4985de70b9bbb4719ffd293d5565513e04ac20e42e6e5583f"},
-    {file = "lxml-4.6.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:1d87936cb5801c557f3e981c9c193861264c01209cb3ad0964a16310ca1b3301"},
-    {file = "lxml-4.6.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:2d5896ddf5389560257bbe89317ca7bcb4e54a02b53a3e572e1ce4226512b51b"},
-    {file = "lxml-4.6.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9b06690224258db5cd39a84e993882a6874676f5de582da57f3df3a82ead9174"},
-    {file = "lxml-4.6.1-cp39-cp39-win32.whl", hash = "sha256:bb252f802f91f59767dcc559744e91efa9df532240a502befd874b54571417bd"},
-    {file = "lxml-4.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ecaef52fd9b9535ae5f01a1dd2651f6608e4ec9dc136fc4dfe7ebe3c3ddb230"},
-    {file = "lxml-4.6.1.tar.gz", hash = "sha256:c152b2e93b639d1f36ec5a8ca24cde4a8eefb2b6b83668fcd8e83a67badcb367"},
+    { file = "lxml-4.6.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:df7c53783a46febb0e70f6b05df2ba104610f2fb0d27023409734a3ecbb78fb2" },
+    { file = "lxml-4.6.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1b7584d421d254ab86d4f0b13ec662a9014397678a7c4265a02a6d7c2b18a75f" },
+    { file = "lxml-4.6.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:079f3ae844f38982d156efce585bc540c16a926d4436712cf4baee0cce487a3d" },
+    { file = "lxml-4.6.3-cp27-cp27m-win32.whl", hash = "sha256:bc4313cbeb0e7a416a488d72f9680fffffc645f8a838bd2193809881c67dd106" },
+    { file = "lxml-4.6.3-cp27-cp27m-win_amd64.whl", hash = "sha256:8157dadbb09a34a6bd95a50690595e1fa0af1a99445e2744110e3dca7831c4ee" },
+    { file = "lxml-4.6.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7728e05c35412ba36d3e9795ae8995e3c86958179c9770e65558ec3fdfd3724f" },
+    { file = "lxml-4.6.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4bff24dfeea62f2e56f5bab929b4428ae6caba2d1eea0c2d6eb618e30a71e6d4" },
+    { file = "lxml-4.6.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:74f7d8d439b18fa4c385f3f5dfd11144bb87c1da034a466c5b5577d23a1d9b51" },
+    { file = "lxml-4.6.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f90ba11136bfdd25cae3951af8da2e95121c9b9b93727b1b896e3fa105b2f586" },
+    { file = "lxml-4.6.3-cp35-cp35m-win32.whl", hash = "sha256:f2380a6376dfa090227b663f9678150ef27543483055cc327555fb592c5967e2" },
+    { file = "lxml-4.6.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c4f05c5a7c49d2fb70223d0d5bcfbe474cf928310ac9fa6a7c6dddc831d0b1d4" },
+    { file = "lxml-4.6.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d2e35d7bf1c1ac8c538f88d26b396e73dd81440d59c1ef8522e1ea77b345ede4" },
+    { file = "lxml-4.6.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:289e9ca1a9287f08daaf796d96e06cb2bc2958891d7911ac7cae1c5f9e1e0ee3" },
+    { file = "lxml-4.6.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bccbfc27563652de7dc9bdc595cb25e90b59c5f8e23e806ed0fd623755b6565d" },
+    { file = "lxml-4.6.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:820628b7b3135403540202e60551e741f9b6d3304371712521be939470b454ec" },
+    { file = "lxml-4.6.3-cp36-cp36m-win32.whl", hash = "sha256:5a0a14e264069c03e46f926be0d8919f4105c1623d620e7ec0e612a2e9bf1c04" },
+    { file = "lxml-4.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:92e821e43ad382332eade6812e298dc9701c75fe289f2a2d39c7960b43d1e92a" },
+    { file = "lxml-4.6.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:efd7a09678fd8b53117f6bae4fa3825e0a22b03ef0a932e070c0bdbb3a35e654" },
+    { file = "lxml-4.6.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:efac139c3f0bf4f0939f9375af4b02c5ad83a622de52d6dfa8e438e8e01d0eb0" },
+    {file = "lxml-4.6.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0fbcf5565ac01dff87cbfc0ff323515c823081c5777a9fc7703ff58388c258c3"},
+    {file = "lxml-4.6.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:122fba10466c7bd4178b07dba427aa516286b846b2cbd6f6169141917283aae2"},
+    {file = "lxml-4.6.3-cp37-cp37m-win32.whl", hash = "sha256:3439c71103ef0e904ea0a1901611863e51f50b5cd5e8654a151740fde5e1cade"},
+    {file = "lxml-4.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:4289728b5e2000a4ad4ab8da6e1db2e093c63c08bdc0414799ee776a3f78da4b"},
+    {file = "lxml-4.6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b007cbb845b28db4fb8b6a5cdcbf65bacb16a8bd328b53cbc0698688a68e1caa"},
+    {file = "lxml-4.6.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:76fa7b1362d19f8fbd3e75fe2fb7c79359b0af8747e6f7141c338f0bee2f871a"},
+    {file = "lxml-4.6.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:26e761ab5b07adf5f555ee82fb4bfc35bf93750499c6c7614bd64d12aaa67927"},
+    {file = "lxml-4.6.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:66e575c62792c3f9ca47cb8b6fab9e35bab91360c783d1606f758761810c9791"},
+    {file = "lxml-4.6.3-cp38-cp38-win32.whl", hash = "sha256:89b8b22a5ff72d89d48d0e62abb14340d9e99fd637d046c27b8b257a01ffbe28"},
+    {file = "lxml-4.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:2a9d50e69aac3ebee695424f7dbd7b8c6d6eb7de2a2eb6b0f6c7db6aa41e02b7"},
+    {file = "lxml-4.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ce256aaa50f6cc9a649c51be3cd4ff142d67295bfc4f490c9134d0f9f6d58ef0"},
+    {file = "lxml-4.6.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:7610b8c31688f0b1be0ef882889817939490a36d0ee880ea562a4e1399c447a1"},
+    {file = "lxml-4.6.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f8380c03e45cf09f8557bdaa41e1fa7c81f3ae22828e1db470ab2a6c96d8bc23"},
+    {file = "lxml-4.6.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:884ab9b29feaca361f7f88d811b1eea9bfca36cf3da27768d28ad45c3ee6f969"},
+    {file = "lxml-4.6.3-cp39-cp39-win32.whl", hash = "sha256:33bb934a044cf32157c12bfcfbb6649807da20aa92c062ef51903415c704704f"},
+    {file = "lxml-4.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:542d454665a3e277f76954418124d67516c5f88e51a900365ed54a9806122b83"},
+    {file = "lxml-4.6.3.tar.gz", hash = "sha256:39b78571b3b30645ac77b95f7c69d1bffc4cf8c3b157c435a34da72e78c82468"},
 ]
 markdown = [
-    {file = "Markdown-3.3.3-py3-none-any.whl", hash = "sha256:c109c15b7dc20a9ac454c9e6025927d44460b85bd039da028d85e2b6d0bcc328"},
-    {file = "Markdown-3.3.3.tar.gz", hash = "sha256:5d9f2b5ca24bc4c7a390d22323ca4bad200368612b5aaa7796babf971d2b2f18"},
+    {file = "Markdown-3.3.4-py3-none-any.whl", hash = "sha256:96c3ba1261de2f7547b46a00ea8463832c921d3f9d6aba3f255a6f71386db20c"},
+    {file = "Markdown-3.3.4.tar.gz", hash = "sha256:31b5b491868dcc87d6c24b7e3d19a0d730d59d3e46f4eea6430a321bed387a49"},
 ]
 markupsafe = [
     {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"},
@@ -1471,11 +1416,6 @@ markupsafe = [
     {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"},
     {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"},
     {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"},
-    {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"},
-    {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"},
-    {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"},
-    {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"},
-    {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"},
     {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"},
 ]
 mccabe = [
@@ -1490,104 +1430,102 @@ mkdocs = [
     {file = "mkdocs-1.1.2.tar.gz", hash = "sha256:f0b61e5402b99d7789efa032c7a74c90a20220a9c81749da06dbfbcbd52ffb39"},
 ]
 mkdocs-material = [
-    {file = "mkdocs-material-6.1.2.tar.gz", hash = "sha256:2c3a35cf3dc0f7b97cf7e0cd22c160a030b2a7841643717c573a93e45a602e7a"},
-    {file = "mkdocs_material-6.1.2-py2.py3-none-any.whl", hash = "sha256:1a3676d5e5fe155c858ca56aa6c272e1da07a2cf2c9f217357c0f890333b28f3"},
+    { file = "mkdocs-material-7.1.3.tar.gz", hash = "sha256:e34bba93ad1a0e6f9afc371f4ef55bedabbf13b9a786b013b0ce26ac55ec2932" },
+    { file = "mkdocs_material-7.1.3-py2.py3-none-any.whl", hash = "sha256:437638b0de7a9113d7f1c9ddc93c0a29a3b808c71c3606713d8c1fa437697a3e" },
 ]
 mkdocs-material-extensions = [
     {file = "mkdocs-material-extensions-1.0.1.tar.gz", hash = "sha256:6947fb7f5e4291e3c61405bad3539d81e0b3cd62ae0d66ced018128af509c68f"},
     {file = "mkdocs_material_extensions-1.0.1-py3-none-any.whl", hash = "sha256:d90c807a88348aa6d1805657ec5c0b2d8d609c110e62b9dce4daf7fa981fa338"},
 ]
 mock = [
-    {file = "mock-4.0.2-py3-none-any.whl", hash = "sha256:3f9b2c0196c60d21838f307f5825a7b86b678cedc58ab9e50a8988187b4d81e0"},
-    {file = "mock-4.0.2.tar.gz", hash = "sha256:dd33eb70232b6118298d516bbcecd26704689c386594f0f3c4f13867b2c56f72"},
+    {file = "mock-4.0.3-py3-none-any.whl", hash = "sha256:122fcb64ee37cfad5b3f48d7a7d51875d7031aaf3d8be7c42e2bee25044eee62"},
+    {file = "mock-4.0.3.tar.gz", hash = "sha256:7d3fbbde18228f4ff2f1f119a45cdffa458b4c0dee32eb4d2bb2f82554bac7bc"},
 ]
 more-itertools = [
-    {file = "more-itertools-8.6.0.tar.gz", hash = "sha256:b3a9005928e5bed54076e6e549c792b306fddfe72b2d1d22dd63d42d5d3899cf"},
-    {file = "more_itertools-8.6.0-py3-none-any.whl", hash = "sha256:8e1a2a43b2f2727425f2b5839587ae37093f19153dc26c0927d1048ff6557330"},
+    {file = "more-itertools-8.7.0.tar.gz", hash = "sha256:c5d6da9ca3ff65220c3bfd2a8db06d698f05d4d2b9be57e1deb2be5a45019713"},
+    {file = "more_itertools-8.7.0-py3-none-any.whl", hash = "sha256:5652a9ac72209ed7df8d9c15daf4e1aa0e3d2ccd3c87f8265a0673cd9cbc9ced"},
 ]
 msgpack = [
-    {file = "msgpack-1.0.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:cec8bf10981ed70998d98431cd814db0ecf3384e6b113366e7f36af71a0fca08"},
-    {file = "msgpack-1.0.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aa5c057eab4f40ec47ea6f5a9825846be2ff6bf34102c560bad5cad5a677c5be"},
-    {file = "msgpack-1.0.0-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:4233b7f86c1208190c78a525cd3828ca1623359ef48f78a6fea4b91bb995775a"},
-    {file = "msgpack-1.0.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:b3758dfd3423e358bbb18a7cccd1c74228dffa7a697e5be6cb9535de625c0dbf"},
-    {file = "msgpack-1.0.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:25b3bc3190f3d9d965b818123b7752c5dfb953f0d774b454fd206c18fe384fb8"},
-    {file = "msgpack-1.0.0-cp36-cp36m-win32.whl", hash = "sha256:e7bbdd8e2b277b77782f3ce34734b0dfde6cbe94ddb74de8d733d603c7f9e2b1"},
-    {file = "msgpack-1.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5dba6d074fac9b24f29aaf1d2d032306c27f04187651511257e7831733293ec2"},
-    {file = "msgpack-1.0.0-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:908944e3f038bca67fcfedb7845c4a257c7749bf9818632586b53bcf06ba4b97"},
-    {file = "msgpack-1.0.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:db685187a415f51d6b937257474ca72199f393dad89534ebbdd7d7a3b000080e"},
-    {file = "msgpack-1.0.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ea41c9219c597f1d2bf6b374d951d310d58684b5de9dc4bd2976db9e1e22c140"},
-    {file = "msgpack-1.0.0-cp37-cp37m-win32.whl", hash = "sha256:e35b051077fc2f3ce12e7c6a34cf309680c63a842db3a0616ea6ed25ad20d272"},
-    {file = "msgpack-1.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5bea44181fc8e18eed1d0cd76e355073f00ce232ff9653a0ae88cb7d9e643322"},
-    {file = "msgpack-1.0.0-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c901e8058dd6653307906c5f157f26ed09eb94a850dddd989621098d347926ab"},
-    {file = "msgpack-1.0.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:271b489499a43af001a2e42f42d876bb98ccaa7e20512ff37ca78c8e12e68f84"},
-    {file = "msgpack-1.0.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7a22c965588baeb07242cb561b63f309db27a07382825fc98aecaf0827c1538e"},
-    {file = "msgpack-1.0.0-cp38-cp38-win32.whl", hash = "sha256:002a0d813e1f7b60da599bdf969e632074f9eec1b96cbed8fb0973a63160a408"},
-    {file = "msgpack-1.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:39c54fdebf5fa4dda733369012c59e7d085ebdfe35b6cf648f09d16708f1be5d"},
-    {file = "msgpack-1.0.0.tar.gz", hash = "sha256:9534d5cc480d4aff720233411a1f765be90885750b07df772380b34c10ecb5c0"},
+    {file = "msgpack-1.0.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:b6d9e2dae081aa35c44af9c4298de4ee72991305503442a5c74656d82b581fe9"},
+    {file = "msgpack-1.0.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a99b144475230982aee16b3d249170f1cccebf27fb0a08e9f603b69637a62192"},
+    {file = "msgpack-1.0.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1026dcc10537d27dd2d26c327e552f05ce148977e9d7b9f1718748281b38c841"},
+    {file = "msgpack-1.0.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:fe07bc6735d08e492a327f496b7850e98cb4d112c56df69b0c844dbebcbb47f6"},
+    {file = "msgpack-1.0.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:9ea52fff0473f9f3000987f313310208c879493491ef3ccf66268eff8d5a0326"},
+    {file = "msgpack-1.0.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:26a1759f1a88df5f1d0b393eb582ec022326994e311ba9c5818adc5374736439"},
+    {file = "msgpack-1.0.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:497d2c12426adcd27ab83144057a705efb6acc7e85957a51d43cdcf7f258900f"},
+    {file = "msgpack-1.0.2-cp36-cp36m-win32.whl", hash = "sha256:e89ec55871ed5473a041c0495b7b4e6099f6263438e0bd04ccd8418f92d5d7f2"},
+    {file = "msgpack-1.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a4355d2193106c7aa77c98fc955252a737d8550320ecdb2e9ac701e15e2943bc"},
+    {file = "msgpack-1.0.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:d6c64601af8f3893d17ec233237030e3110f11b8a962cb66720bf70c0141aa54"},
+    {file = "msgpack-1.0.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f484cd2dca68502de3704f056fa9b318c94b1539ed17a4c784266df5d6978c87"},
+    {file = "msgpack-1.0.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f3e6aaf217ac1c7ce1563cf52a2f4f5d5b1f64e8729d794165db71da57257f0c"},
+    {file = "msgpack-1.0.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:8521e5be9e3b93d4d5e07cb80b7e32353264d143c1f072309e1863174c6aadb1"},
+    {file = "msgpack-1.0.2-cp37-cp37m-win32.whl", hash = "sha256:31c17bbf2ae5e29e48d794c693b7ca7a0c73bd4280976d408c53df421e838d2a"},
+    {file = "msgpack-1.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8ffb24a3b7518e843cd83538cf859e026d24ec41ac5721c18ed0c55101f9775b"},
+    {file = "msgpack-1.0.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:b28c0876cce1466d7c2195d7658cf50e4730667196e2f1355c4209444717ee06"},
+    {file = "msgpack-1.0.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:87869ba567fe371c4555d2e11e4948778ab6b59d6cc9d8460d543e4cfbbddd1c"},
+    {file = "msgpack-1.0.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b55f7db883530b74c857e50e149126b91bb75d35c08b28db12dcb0346f15e46e"},
+    {file = "msgpack-1.0.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:ac25f3e0513f6673e8b405c3a80500eb7be1cf8f57584be524c4fa78fe8e0c83"},
+    {file = "msgpack-1.0.2-cp38-cp38-win32.whl", hash = "sha256:0cb94ee48675a45d3b86e61d13c1e6f1696f0183f0715544976356ff86f741d9"},
+    {file = "msgpack-1.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:e36a812ef4705a291cdb4a2fd352f013134f26c6ff63477f20235138d1d21009"},
+    {file = "msgpack-1.0.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2a5866bdc88d77f6e1370f82f2371c9bc6fc92fe898fa2dec0c5d4f5435a2694"},
+    {file = "msgpack-1.0.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:92be4b12de4806d3c36810b0fe2aeedd8d493db39e2eb90742b9c09299eb5759"},
+    {file = "msgpack-1.0.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:de6bd7990a2c2dabe926b7e62a92886ccbf809425c347ae7de277067f97c2887"},
+    {file = "msgpack-1.0.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5a9ee2540c78659a1dd0b110f73773533ee3108d4e1219b5a15a8d635b7aca0e"},
+    {file = "msgpack-1.0.2-cp39-cp39-win32.whl", hash = "sha256:c747c0cc08bd6d72a586310bda6ea72eeb28e7505990f342552315b229a19b33"},
+    {file = "msgpack-1.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:d8167b84af26654c1124857d71650404336f4eb5cc06900667a493fc619ddd9f"},
+    {file = "msgpack-1.0.2.tar.gz", hash = "sha256:fae04496f5bc150eefad4e9571d1a76c55d021325dcd484ce45065ebbdd00984"},
 ]
 nltk = [
-    {file = "nltk-3.5.zip", hash = "sha256:845365449cd8c5f9731f7cb9f8bd6fd0767553b9d53af9eb1b3abf7700936b35"},
+    { file = "nltk-3.6.2-py3-none-any.whl", hash = "sha256:240e23ab1ab159ef9940777d30c7c72d7e76d91877099218a7585370c11f6b9e" },
+    { file = "nltk-3.6.2.zip", hash = "sha256:57d556abed621ab9be225cc6d2df1edce17572efb67a3d754630c9f8381503eb" },
 ]
 nox = [
     {file = "nox-2019.11.9-py2.py3-none-any.whl", hash = "sha256:0f4b489fdd0eb5665f8c5ee89e5aeb648beae6ccbb363b2492a6786f26e70d85"},
     {file = "nox-2019.11.9.tar.gz", hash = "sha256:22d0f45ad2bd2d75fa4a243d8d8b84359dbf43134ec5cbff4de9f243b6d528b8"},
 ]
 outcome = [
-    {file = "outcome-1.0.1-py2.py3-none-any.whl", hash = "sha256:ee46c5ce42780cde85d55a61819d0e6b8cb490f1dbd749ba75ff2629771dcd2d"},
-    {file = "outcome-1.0.1.tar.gz", hash = "sha256:fc7822068ba7dd0fc2532743611e8a73246708d3564e29a39f93d6ab3701b66f"},
+    {file = "outcome-1.1.0-py2.py3-none-any.whl", hash = "sha256:c7dd9375cfd3c12db9801d080a3b63d4b0a261aa996c4c13152380587288d958"},
+    {file = "outcome-1.1.0.tar.gz", hash = "sha256:e862f01d4e626e63e8f92c38d1f8d5546d3f9cce989263c521b2e7990d186967"},
 ]
 packaging = [
-    {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"},
-    {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"},
+    {file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"},
+    {file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"},
 ]
 parsel = [
     {file = "parsel-1.6.0-py2.py3-none-any.whl", hash = "sha256:9e1fa8db1c0b4a878bf34b35c043d89c9d1cbebc23b4d34dbc3c0ec33f2e087d"},
     {file = "parsel-1.6.0.tar.gz", hash = "sha256:70efef0b651a996cceebc69e55a85eb2233be0890959203ba7c3a03c72725c79"},
 ]
 pbr = [
-    {file = "pbr-5.5.1-py2.py3-none-any.whl", hash = "sha256:b236cde0ac9a6aedd5e3c34517b423cd4fd97ef723849da6b0d2231142d89c00"},
-    {file = "pbr-5.5.1.tar.gz", hash = "sha256:5fad80b613c402d5b7df7bd84812548b2a61e9977387a80a5fc5c396492b13c9"},
+    { file = "pbr-5.6.0-py2.py3-none-any.whl", hash = "sha256:c68c661ac5cc81058ac94247278eeda6d2e6aecb3e227b0387c30d277e7ef8d4" },
+    { file = "pbr-5.6.0.tar.gz", hash = "sha256:42df03e7797b796625b1029c0400279c7c34fd7df24a7d7818a1abb5b38710dd" },
 ]
 pluggy = [
     {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
     {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
 ]
-psutil = [
-    {file = "psutil-5.7.3-cp27-none-win32.whl", hash = "sha256:1cd6a0c9fb35ece2ccf2d1dd733c1e165b342604c67454fd56a4c12e0a106787"},
-    {file = "psutil-5.7.3-cp27-none-win_amd64.whl", hash = "sha256:e02c31b2990dcd2431f4524b93491941df39f99619b0d312dfe1d4d530b08b4b"},
-    {file = "psutil-5.7.3-cp35-cp35m-win32.whl", hash = "sha256:56c85120fa173a5d2ad1d15a0c6e0ae62b388bfb956bb036ac231fbdaf9e4c22"},
-    {file = "psutil-5.7.3-cp35-cp35m-win_amd64.whl", hash = "sha256:fa38ac15dbf161ab1e941ff4ce39abd64b53fec5ddf60c23290daed2bc7d1157"},
-    {file = "psutil-5.7.3-cp36-cp36m-win32.whl", hash = "sha256:01bc82813fbc3ea304914581954979e637bcc7084e59ac904d870d6eb8bb2bc7"},
-    {file = "psutil-5.7.3-cp36-cp36m-win_amd64.whl", hash = "sha256:6a3e1fd2800ca45083d976b5478a2402dd62afdfb719b30ca46cd28bb25a2eb4"},
-    {file = "psutil-5.7.3-cp37-cp37m-win32.whl", hash = "sha256:fbcac492cb082fa38d88587d75feb90785d05d7e12d4565cbf1ecc727aff71b7"},
-    {file = "psutil-5.7.3-cp37-cp37m-win_amd64.whl", hash = "sha256:5d9106ff5ec2712e2f659ebbd112967f44e7d33f40ba40530c485cc5904360b8"},
-    {file = "psutil-5.7.3-cp38-cp38-win32.whl", hash = "sha256:ade6af32eb80a536eff162d799e31b7ef92ddcda707c27bbd077238065018df4"},
-    {file = "psutil-5.7.3-cp38-cp38-win_amd64.whl", hash = "sha256:2cb55ef9591b03ef0104bedf67cc4edb38a3edf015cf8cf24007b99cb8497542"},
-    {file = "psutil-5.7.3.tar.gz", hash = "sha256:af73f7bcebdc538eda9cc81d19db1db7bf26f103f91081d780bbacfcb620dee2"},
-]
 py = [
-    {file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"},
-    {file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"},
+    {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"},
+    {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"},
 ]
 pycodestyle = [
-    {file = "pycodestyle-2.6.0-py2.py3-none-any.whl", hash = "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367"},
-    {file = "pycodestyle-2.6.0.tar.gz", hash = "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"},
+    {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
+    {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
 ]
 pycparser = [
     {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"},
     {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"},
 ]
 pyflakes = [
-    {file = "pyflakes-2.2.0-py2.py3-none-any.whl", hash = "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92"},
-    {file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"},
+    { file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3" },
+    { file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db" },
 ]
 pygments = [
-    {file = "Pygments-2.7.2-py3-none-any.whl", hash = "sha256:88a0bbcd659fcb9573703957c6b9cff9fab7295e6e76db54c9d00ae42df32773"},
-    {file = "Pygments-2.7.2.tar.gz", hash = "sha256:381985fcc551eb9d37c52088a32914e00517e57f4a21609f48141ba08e193fa0"},
+    {file = "Pygments-2.8.1-py3-none-any.whl", hash = "sha256:534ef71d539ae97d4c3a4cf7d6f110f214b0e687e92f9cb9d2a3b0d3101289c8"},
+    {file = "Pygments-2.8.1.tar.gz", hash = "sha256:2656e1a6edcdabf4275f9a3640db59fd5de107d88e8663c5d4e9a0fa62f77f94"},
 ]
 pymdown-extensions = [
-    {file = "pymdown-extensions-8.0.1.tar.gz", hash = "sha256:9ba704052d4bdc04a7cd63f7db4ef6add73bafcef22c0cf6b2e3386cf4ece51e"},
-    {file = "pymdown_extensions-8.0.1-py2.py3-none-any.whl", hash = "sha256:a3689c04f4cbddacd9d569425c571ae07e2673cc4df63a26cdbf1abc15229137"},
+    {file = "pymdown-extensions-8.1.1.tar.gz", hash = "sha256:632371fa3bf1b21a0e3f4063010da59b41db049f261f4c0b0872069a9b6d1735"},
+    {file = "pymdown_extensions-8.1.1-py3-none-any.whl", hash = "sha256:478b2c04513fbb2db61688d5f6e9030a92fb9be14f1f383535c43f7be9dff95b"},
 ]
 pyparsing = [
     {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
@@ -1601,59 +1539,87 @@ pytest-mock = [
     {file = "pytest-mock-2.0.0.tar.gz", hash = "sha256:b35eb281e93aafed138db25c8772b95d3756108b601947f89af503f8c629413f"},
     {file = "pytest_mock-2.0.0-py2.py3-none-any.whl", hash = "sha256:cb67402d87d5f53c579263d37971a164743dc33c159dfb4fb4a86f37c5552307"},
 ]
-pytest-trio = [
-    {file = "pytest-trio-0.6.0.tar.gz", hash = "sha256:9bf0a490fd177a33617e8709242293fae47934de2b51f8209eb2c0545b6ca8fe"},
-    {file = "pytest_trio-0.6.0-py3-none-any.whl", hash = "sha256:3f48cc1df66d279d705af38ad38d1639c2e2380ddffcdc3a45bb81758de61f03"},
-]
 pyyaml = [
-    {file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"},
-    {file = "PyYAML-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76"},
-    {file = "PyYAML-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2"},
-    {file = "PyYAML-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c"},
-    {file = "PyYAML-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2"},
-    {file = "PyYAML-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648"},
-    {file = "PyYAML-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"},
-    {file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"},
-    {file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"},
-    {file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"},
-    {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"},
+    { file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922" },
+    { file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393" },
+    { file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8" },
+    { file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185" },
+    { file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253" },
+    { file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc" },
+    { file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347" },
+    { file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541" },
+    { file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5" },
+    { file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df" },
+    { file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018" },
+    { file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63" },
+    { file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa" },
+    { file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0" },
+    { file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b" },
+    { file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf" },
+    { file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46" },
+    { file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb" },
+    { file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247" },
+    { file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc" },
+    { file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc" },
+    { file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696" },
+    { file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77" },
+    { file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183" },
+    { file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122" },
+    { file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6" },
+    { file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10" },
+    { file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db" },
+    { file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e" },
 ]
 regex = [
-    {file = "regex-2020.10.28-cp27-cp27m-win32.whl", hash = "sha256:4b5a9bcb56cc146c3932c648603b24514447eafa6ce9295234767bf92f69b504"},
-    {file = "regex-2020.10.28-cp27-cp27m-win_amd64.whl", hash = "sha256:c13d311a4c4a8d671f5860317eb5f09591fbe8259676b86a85769423b544451e"},
-    {file = "regex-2020.10.28-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c8a2b7ccff330ae4c460aff36626f911f918555660cc28163417cb84ffb25789"},
-    {file = "regex-2020.10.28-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4afa350f162551cf402bfa3cd8302165c8e03e689c897d185f16a167328cc6dd"},
-    {file = "regex-2020.10.28-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:b88fa3b8a3469f22b4f13d045d9bd3eda797aa4e406fde0a2644bc92bbdd4bdd"},
-    {file = "regex-2020.10.28-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:f43109822df2d3faac7aad79613f5f02e4eab0fc8ad7932d2e70e2a83bd49c26"},
-    {file = "regex-2020.10.28-cp36-cp36m-win32.whl", hash = "sha256:8092a5a06ad9a7a247f2a76ace121183dc4e1a84c259cf9c2ce3bbb69fac3582"},
-    {file = "regex-2020.10.28-cp36-cp36m-win_amd64.whl", hash = "sha256:49461446b783945597c4076aea3f49aee4b4ce922bd241e4fcf62a3e7c61794c"},
-    {file = "regex-2020.10.28-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:8ca9dca965bd86ea3631b975d63b0693566d3cc347e55786d5514988b6f5b84c"},
-    {file = "regex-2020.10.28-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ea37320877d56a7f0a1e6a625d892cf963aa7f570013499f5b8d5ab8402b5625"},
-    {file = "regex-2020.10.28-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:3a5f08039eee9ea195a89e180c5762bfb55258bfb9abb61a20d3abee3b37fd12"},
-    {file = "regex-2020.10.28-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:cb905f3d2e290a8b8f1579d3984f2cfa7c3a29cc7cba608540ceeed18513f520"},
-    {file = "regex-2020.10.28-cp37-cp37m-win32.whl", hash = "sha256:a62162be05edf64f819925ea88d09d18b09bebf20971b363ce0c24e8b4aa14c0"},
-    {file = "regex-2020.10.28-cp37-cp37m-win_amd64.whl", hash = "sha256:03855ee22980c3e4863dc84c42d6d2901133362db5daf4c36b710dd895d78f0a"},
-    {file = "regex-2020.10.28-cp38-cp38-manylinux1_i686.whl", hash = "sha256:625116aca6c4b57c56ea3d70369cacc4d62fead4930f8329d242e4fe7a58ce4b"},
-    {file = "regex-2020.10.28-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2dc522e25e57e88b4980d2bdd334825dbf6fa55f28a922fc3bfa60cc09e5ef53"},
-    {file = "regex-2020.10.28-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:119e0355dbdd4cf593b17f2fc5dbd4aec2b8899d0057e4957ba92f941f704bf5"},
-    {file = "regex-2020.10.28-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:cfcf28ed4ce9ced47b9b9670a4f0d3d3c0e4d4779ad4dadb1ad468b097f808aa"},
-    {file = "regex-2020.10.28-cp38-cp38-win32.whl", hash = "sha256:06b52815d4ad38d6524666e0d50fe9173533c9cc145a5779b89733284e6f688f"},
-    {file = "regex-2020.10.28-cp38-cp38-win_amd64.whl", hash = "sha256:c3466a84fce42c2016113101018a9981804097bacbab029c2d5b4fcb224b89de"},
-    {file = "regex-2020.10.28-cp39-cp39-manylinux1_i686.whl", hash = "sha256:c2c6c56ee97485a127555c9595c069201b5161de9d05495fbe2132b5ac104786"},
-    {file = "regex-2020.10.28-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1ec66700a10e3c75f1f92cbde36cca0d3aaee4c73dfa26699495a3a30b09093c"},
-    {file = "regex-2020.10.28-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:11116d424734fe356d8777f89d625f0df783251ada95d6261b4c36ad27a394bb"},
-    {file = "regex-2020.10.28-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:f1fce1e4929157b2afeb4bb7069204d4370bab9f4fc03ca1fbec8bd601f8c87d"},
-    {file = "regex-2020.10.28-cp39-cp39-win32.whl", hash = "sha256:832339223b9ce56b7b15168e691ae654d345ac1635eeb367ade9ecfe0e66bee0"},
-    {file = "regex-2020.10.28-cp39-cp39-win_amd64.whl", hash = "sha256:654c1635f2313d0843028487db2191530bca45af61ca85d0b16555c399625b0e"},
-    {file = "regex-2020.10.28.tar.gz", hash = "sha256:dd3e6547ecf842a29cf25123fbf8d2461c53c8d37aa20d87ecee130c89b7079b"},
+    { file = "regex-2021.4.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:619d71c59a78b84d7f18891fe914446d07edd48dc8328c8e149cbe0929b4e000" },
+    { file = "regex-2021.4.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:47bf5bf60cf04d72bf6055ae5927a0bd9016096bf3d742fa50d9bf9f45aa0711" },
+    { file = "regex-2021.4.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:281d2fd05555079448537fe108d79eb031b403dac622621c78944c235f3fcf11" },
+    { file = "regex-2021.4.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:bd28bc2e3a772acbb07787c6308e00d9626ff89e3bfcdebe87fa5afbfdedf968" },
+    { file = "regex-2021.4.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7c2a1af393fcc09e898beba5dd59196edaa3116191cc7257f9224beaed3e1aa0" },
+    { file = "regex-2021.4.4-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c38c71df845e2aabb7fb0b920d11a1b5ac8526005e533a8920aea97efb8ec6a4" },
+    { file = "regex-2021.4.4-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:96fcd1888ab4d03adfc9303a7b3c0bd78c5412b2bfbe76db5b56d9eae004907a" },
+    { file = "regex-2021.4.4-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:ade17eb5d643b7fead300a1641e9f45401c98eee23763e9ed66a43f92f20b4a7" },
+    { file = "regex-2021.4.4-cp36-cp36m-win32.whl", hash = "sha256:e8e5b509d5c2ff12f8418006d5a90e9436766133b564db0abaec92fd27fcee29" },
+    { file = "regex-2021.4.4-cp36-cp36m-win_amd64.whl", hash = "sha256:11d773d75fa650cd36f68d7ca936e3c7afaae41b863b8c387a22aaa78d3c5c79" },
+    { file = "regex-2021.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d3029c340cfbb3ac0a71798100ccc13b97dddf373a4ae56b6a72cf70dfd53bc8" },
+    { file = "regex-2021.4.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:18c071c3eb09c30a264879f0d310d37fe5d3a3111662438889ae2eb6fc570c31" },
+    { file = "regex-2021.4.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:4c557a7b470908b1712fe27fb1ef20772b78079808c87d20a90d051660b1d69a" },
+    { file = "regex-2021.4.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:01afaf2ec48e196ba91b37451aa353cb7eda77efe518e481707e0515025f0cd5" },
+    { file = "regex-2021.4.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:3a9cd17e6e5c7eb328517969e0cb0c3d31fd329298dd0c04af99ebf42e904f82" },
+    { file = "regex-2021.4.4-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:90f11ff637fe8798933fb29f5ae1148c978cccb0452005bf4c69e13db951e765" },
+    { file = "regex-2021.4.4-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:919859aa909429fb5aa9cf8807f6045592c85ef56fdd30a9a3747e513db2536e" },
+    { file = "regex-2021.4.4-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:339456e7d8c06dd36a22e451d58ef72cef293112b559010db3d054d5560ef439" },
+    { file = "regex-2021.4.4-cp37-cp37m-win32.whl", hash = "sha256:67bdb9702427ceddc6ef3dc382455e90f785af4c13d495f9626861763ee13f9d" },
+    { file = "regex-2021.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:32e65442138b7b76dd8173ffa2cf67356b7bc1768851dded39a7a13bf9223da3" },
+    { file = "regex-2021.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1e1c20e29358165242928c2de1482fb2cf4ea54a6a6dea2bd7a0e0d8ee321500" },
+    { file = "regex-2021.4.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:314d66636c494ed9c148a42731b3834496cc9a2c4251b1661e40936814542b14" },
+    { file = "regex-2021.4.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6d1b01031dedf2503631d0903cb563743f397ccaf6607a5e3b19a3d76fc10480" },
+    { file = "regex-2021.4.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:741a9647fcf2e45f3a1cf0e24f5e17febf3efe8d4ba1281dcc3aa0459ef424dc" },
+    { file = "regex-2021.4.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4c46e22a0933dd783467cf32b3516299fb98cfebd895817d685130cc50cd1093" },
+    { file = "regex-2021.4.4-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:e512d8ef5ad7b898cdb2d8ee1cb09a8339e4f8be706d27eaa180c2f177248a10" },
+    { file = "regex-2021.4.4-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:980d7be47c84979d9136328d882f67ec5e50008681d94ecc8afa8a65ed1f4a6f" },
+    { file = "regex-2021.4.4-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:ce15b6d103daff8e9fee13cf7f0add05245a05d866e73926c358e871221eae87" },
+    { file = "regex-2021.4.4-cp38-cp38-win32.whl", hash = "sha256:a91aa8619b23b79bcbeb37abe286f2f408d2f2d6f29a17237afda55bb54e7aac" },
+    { file = "regex-2021.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:c0502c0fadef0d23b128605d69b58edb2c681c25d44574fc673b0e52dce71ee2" },
+    { file = "regex-2021.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:598585c9f0af8374c28edd609eb291b5726d7cbce16be6a8b95aa074d252ee17" },
+    { file = "regex-2021.4.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:ee54ff27bf0afaf4c3b3a62bcd016c12c3fdb4ec4f413391a90bd38bc3624605" },
+    { file = "regex-2021.4.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7d9884d86dd4dd489e981d94a65cd30d6f07203d90e98f6f657f05170f6324c9" },
+    { file = "regex-2021.4.4-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:bf5824bfac591ddb2c1f0a5f4ab72da28994548c708d2191e3b87dd207eb3ad7" },
+    { file = "regex-2021.4.4-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:563085e55b0d4fb8f746f6a335893bda5c2cef43b2f0258fe1020ab1dd874df8" },
+    { file = "regex-2021.4.4-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9c3db21af35e3b3c05764461b262d6f05bbca08a71a7849fd79d47ba7bc33ed" },
+    { file = "regex-2021.4.4-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:3916d08be28a1149fb97f7728fca1f7c15d309a9f9682d89d79db75d5e52091c" },
+    { file = "regex-2021.4.4-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:fd45ff9293d9274c5008a2054ecef86a9bfe819a67c7be1afb65e69b405b3042" },
+    { file = "regex-2021.4.4-cp39-cp39-win32.whl", hash = "sha256:fa4537fb4a98fe8fde99626e4681cc644bdcf2a795038533f9f711513a862ae6" },
+    { file = "regex-2021.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:97f29f57d5b84e73fbaf99ab3e26134e6687348e95ef6b48cfd2c06807005a07" },
+    { file = "regex-2021.4.4.tar.gz", hash = "sha256:52ba3d3f9b942c49d7e4bc105bb28551c44065f139a65062ab7912bef10c9afb" },
 ]
 requests = [
-    {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"},
-    {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"},
+    {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"},
+    {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"},
 ]
 respx = [
-    {file = "respx-0.10.1-py2.py3-none-any.whl", hash = "sha256:43aca802e0fd0c964865b07f101943e7b5902ea070ec94cf8e84a39db8729b06"},
-    {file = "respx-0.10.1.tar.gz", hash = "sha256:190d1fb5bddaf6fcc1319a3cdfbd682c77d7167017b3283cbe79b8fb74927135"},
+    {file = "respx-0.16.3-py2.py3-none-any.whl", hash = "sha256:2db35e4af6bf25f58435457da7a0df52b34b8b3c2ea584d8a8cce27a7b00a614"},
+    {file = "respx-0.16.3.tar.gz", hash = "sha256:3f4781a7fc02d6162f63f33c1481b31d83c0b8c54e98a077932a4197182a7312"},
 ]
 rfc3986 = [
     {file = "rfc3986-1.4.0-py2.py3-none-any.whl", hash = "sha256:af9147e9aceda37c91a05f4deb128d4b4b49d6b199775fd2d2927768abdc8f50"},
@@ -1668,20 +1634,20 @@ six = [
     {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"},
 ]
 smmap = [
-    {file = "smmap-3.0.4-py2.py3-none-any.whl", hash = "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4"},
-    {file = "smmap-3.0.4.tar.gz", hash = "sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24"},
+    { file = "smmap-4.0.0-py2.py3-none-any.whl", hash = "sha256:a9a7479e4c572e2e775c404dcd3080c8dc49f39918c2cf74913d30c4c478e3c2" },
+    { file = "smmap-4.0.0.tar.gz", hash = "sha256:7e65386bd122d45405ddf795637b7f7d2b532e7e401d46bbe3fb49b9986d5182" },
 ]
 sniffio = [
     {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"},
     {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"},
 ]
 sortedcontainers = [
-    {file = "sortedcontainers-2.2.2-py2.py3-none-any.whl", hash = "sha256:c633ebde8580f241f274c1f8994a665c0e54a17724fecd0cae2f079e09c36d3f"},
-    {file = "sortedcontainers-2.2.2.tar.gz", hash = "sha256:4e73a757831fc3ca4de2859c422564239a31d8213d09a2a666e375807034d2ba"},
+    {file = "sortedcontainers-2.3.0-py2.py3-none-any.whl", hash = "sha256:37257a32add0a3ee490bb170b599e93095eed89a55da91fa9f48753ea12fd73f"},
+    {file = "sortedcontainers-2.3.0.tar.gz", hash = "sha256:59cc937650cf60d677c16775597c89a960658a09cf7c1a668f86e1e4464b10a1"},
 ]
 stevedore = [
-    {file = "stevedore-3.2.2-py3-none-any.whl", hash = "sha256:5e1ab03eaae06ef6ce23859402de785f08d97780ed774948ef16c4652c41bc62"},
-    {file = "stevedore-3.2.2.tar.gz", hash = "sha256:f845868b3a3a77a2489d226568abe7328b5c2d4f6a011cc759dfa99144a521f0"},
+    {file = "stevedore-3.3.0-py3-none-any.whl", hash = "sha256:50d7b78fbaf0d04cd62411188fa7eedcb03eb7f4c4b37005615ceebe582aa82a"},
+    {file = "stevedore-3.3.0.tar.gz", hash = "sha256:3a5bbd0652bf552748871eaa73a4a8dc2899786bc497a2aa1fcb4dcdb0debeee"},
 ]
 toml = [
     {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
@@ -1731,20 +1697,25 @@ tornado = [
     {file = "tornado-6.1.tar.gz", hash = "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791"},
 ]
 tqdm = [
-    {file = "tqdm-4.51.0-py2.py3-none-any.whl", hash = "sha256:9ad44aaf0fc3697c06f6e05c7cf025dd66bc7bcb7613c66d85f4464c47ac8fad"},
-    {file = "tqdm-4.51.0.tar.gz", hash = "sha256:ef54779f1c09f346b2b5a8e5c61f96fbcb639929e640e59f8cf810794f406432"},
+    { file = "tqdm-4.60.0-py2.py3-none-any.whl", hash = "sha256:daec693491c52e9498632dfbe9ccfc4882a557f5fa08982db1b4d3adbe0887c3" },
+    { file = "tqdm-4.60.0.tar.gz", hash = "sha256:ebdebdb95e3477ceea267decfc0784859aa3df3e27e22d23b83e9b272bf157ae" },
 ]
 trio = [
     {file = "trio-0.17.0-py3-none-any.whl", hash = "sha256:fc70c74e8736d1105b3c05cc2e49b30c58755733740f9c51ae6d88a4d6d0a291"},
     {file = "trio-0.17.0.tar.gz", hash = "sha256:e85cf9858e445465dfbb0e3fdf36efe92082d2df87bfe9d62585eedd6e8e9d7d"},
 ]
+typing-extensions = [
+    {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"},
+    {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"},
+    {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"},
+]
 urllib3 = [
-    {file = "urllib3-1.25.11-py2.py3-none-any.whl", hash = "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"},
-    {file = "urllib3-1.25.11.tar.gz", hash = "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2"},
+    {file = "urllib3-1.26.4-py2.py3-none-any.whl", hash = "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df"},
+    {file = "urllib3-1.26.4.tar.gz", hash = "sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"},
 ]
 virtualenv = [
-    {file = "virtualenv-20.1.0-py2.py3-none-any.whl", hash = "sha256:b0011228208944ce71052987437d3843e05690b2f23d1c7da4263fde104c97a2"},
-    {file = "virtualenv-20.1.0.tar.gz", hash = "sha256:b8d6110f493af256a40d65e29846c69340a947669eec8ce784fcf3dd3af28380"},
+    { file = "virtualenv-20.4.4-py2.py3-none-any.whl", hash = "sha256:a935126db63128861987a7d5d30e23e8ec045a73840eeccb467c148514e29535" },
+    { file = "virtualenv-20.4.4.tar.gz", hash = "sha256:09c61377ef072f43568207dc8e46ddeac6bcdcaf288d49011bda0e7f4d38c4a2" },
 ]
 w3lib = [
     {file = "w3lib-1.22.0-py2.py3-none-any.whl", hash = "sha256:0161d55537063e00d95a241663ede3395c4c6d7b777972ba2fd58bbab2001e53"},
@@ -1755,52 +1726,63 @@ wcwidth = [
     {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
 ]
 zipp = [
-    {file = "zipp-3.4.0-py3-none-any.whl", hash = "sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108"},
-    {file = "zipp-3.4.0.tar.gz", hash = "sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb"},
+    {file = "zipp-3.4.1-py3-none-any.whl", hash = "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098"},
+    {file = "zipp-3.4.1.tar.gz", hash = "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76"},
 ]
 "zope.event" = [
     {file = "zope.event-4.5.0-py2.py3-none-any.whl", hash = "sha256:2666401939cdaa5f4e0c08cf7f20c9b21423b95e88f4675b1443973bdb080c42"},
     {file = "zope.event-4.5.0.tar.gz", hash = "sha256:5e76517f5b9b119acf37ca8819781db6c16ea433f7e2062c4afc2b6fbedb1330"},
 ]
 "zope.interface" = [
-    {file = "zope.interface-5.1.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:f718675fd071bcce4f7cbf9250cbaaf64e2e91ef1b0b32a1af596e7412647556"},
-    {file = "zope.interface-5.1.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b10eb4d0a77609679bf5f23708e20b1cd461a1643bd8ea42b1ca4149b1a5406c"},
-    {file = "zope.interface-5.1.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2c867914f7608674a555ac8daf20265644ac7be709e1da7d818089eebdfe544e"},
-    {file = "zope.interface-5.1.2-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:f9d4bfbd015e4b80dbad11c97049975f94592a6a0440e903ee647309f6252a1f"},
-    {file = "zope.interface-5.1.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:5ffe4e0753393bcbcfc9a58133ed3d3a584634cc7cc2e667f8e3e6fbcbb2155d"},
-    {file = "zope.interface-5.1.2-cp27-cp27m-win32.whl", hash = "sha256:6e5b9a4bf133cf1887b4a04c21c10ca9f548114f19c83957b2820d5c84254940"},
-    {file = "zope.interface-5.1.2-cp27-cp27m-win_amd64.whl", hash = "sha256:2eadac20711a795d3bb7a2bfc87c04091cb5274d9c3281b43088a1227099b662"},
-    {file = "zope.interface-5.1.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7750746421c4395e3d2cc3d805919f4f57bb9f2a9a0ccd955566a9341050a1b4"},
-    {file = "zope.interface-5.1.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:663982381bd428a275a841009e52983cc69c471a4979ce01344fadbf72cf353d"},
-    {file = "zope.interface-5.1.2-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:d867998a56c5133b9d31992beb699892e33b72150a8bf40f86cb52b8c606c83f"},
-    {file = "zope.interface-5.1.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:5aab51b9c1af1b8a84f40aa49ffe1684d41810b18d6c3e94aa50194e0a563f01"},
-    {file = "zope.interface-5.1.2-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:121a9dccfe0c34be9c33b2c28225f0284f9b8e090580ffdff26c38fa16c7ffe1"},
-    {file = "zope.interface-5.1.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:fae50fc12a5e8541f6f1cc4ed744ca8f76a9543876cf63f618fb0e6aca8f8375"},
-    {file = "zope.interface-5.1.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:208e82f73b242275b8566ac07a25158e7b21fa2f14e642a7881048430612d1a6"},
-    {file = "zope.interface-5.1.2-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:b274ac8e511b55ffb62e8292316bd2baa80c10e9fe811b1aa5ce81da6b6697d8"},
-    {file = "zope.interface-5.1.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:fdedce3bc5360bd29d4bb90396e8d4d3c09af49bc0383909fe84c7233c5ee675"},
-    {file = "zope.interface-5.1.2-cp35-cp35m-win32.whl", hash = "sha256:fcf9c8edda7f7b2fd78069e97f4197815df5e871ec47b0f22580d330c6dec561"},
-    {file = "zope.interface-5.1.2-cp35-cp35m-win_amd64.whl", hash = "sha256:3ae8946d51789779f76e4fa326fd6676d8c19c1c3b4c4c5e9342807185264875"},
-    {file = "zope.interface-5.1.2-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:37999d5ebd5d7bcd32438b725ca3470df05a7de8b1e9c0395bef24296b31ca99"},
-    {file = "zope.interface-5.1.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:988f8b2281f3d95c66c01bdb141cefef1cc97db0d473c25c3fe2927ef00293b9"},
-    {file = "zope.interface-5.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1d73d8986f948525536956ddd902e8a587a6846ebf4492117db16daba2865ddf"},
-    {file = "zope.interface-5.1.2-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9f56121d8a676802044584e6cc41250bbcde069d8adf725b9b817a6b0fd87f09"},
-    {file = "zope.interface-5.1.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:590a40447ff3803c44050ce3c17c3958f11ca028dae3eacdd7b96775184394fa"},
-    {file = "zope.interface-5.1.2-cp36-cp36m-win32.whl", hash = "sha256:5636cd7e60583b1608044ae4405e91575399430e66a5e1812f4bf30bcc55864e"},
-    {file = "zope.interface-5.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:7fc8708bc996e50fc7a9a2ad394e1f015348e389da26789fa6916630237143d7"},
-    {file = "zope.interface-5.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:25ea6906f9987d42546329d06f9750e69f0ee62307a2e7092955ed0758e64f09"},
-    {file = "zope.interface-5.1.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:040f833694496065147e76581c0bf32b229a8b8c5eda120a0293afb008222387"},
-    {file = "zope.interface-5.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a1cdd7390d7f66ddcebf545203ca3728c4890d605f9f2697bc8e31437906e8e7"},
-    {file = "zope.interface-5.1.2-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:11198b44e4a3d8c7a80cc20bbdd65522258a4d82fe467cd310c9fcce8ffe2ed2"},
-    {file = "zope.interface-5.1.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6d06bf8e24dd6c473c4fbd8e16a83bd2e6d74add6ba25169043deb46d497b211"},
-    {file = "zope.interface-5.1.2-cp37-cp37m-win32.whl", hash = "sha256:91abd2f080065a7c007540f6bbd93ef7bdbbffa6df4a4cfab3892d8623b83c98"},
-    {file = "zope.interface-5.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:c75b502af2c83fcfa2ee9c2257c1ba5806634a91a50db6129ff70e67c42c7e7b"},
-    {file = "zope.interface-5.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:70a2aed9615645bbe9d82c0f52bc7e676d2c0f8a63933d68418e0cb307f30536"},
-    {file = "zope.interface-5.1.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:2557833df892558123d791d6ff80ac4a2a0351f69c7421c7d5f0c07db72c8865"},
-    {file = "zope.interface-5.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:570e637cb6509998555f7e4af13006d89fad6c09cfc5c4795855385391063e4b"},
-    {file = "zope.interface-5.1.2-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:a0f51536ce6e817a7aa25b0dca8b62feb210d4dc22cabfe8d1a92d47979372cd"},
-    {file = "zope.interface-5.1.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:f61e6b95b414431ffe9dc460928fe9f351095fde074e2c2f5c6dda7b67a2192d"},
-    {file = "zope.interface-5.1.2-cp38-cp38-win32.whl", hash = "sha256:15f3082575e7e19581a80b866664f843719b647a7f7189c811ba7f9ab3309f83"},
-    {file = "zope.interface-5.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb566cab630ec176b2d6115ed08b2cf4d921b47caa7f02cca1b4a9525223ee94"},
-    {file = "zope.interface-5.1.2.tar.gz", hash = "sha256:c9c8e53a5472b77f6a391b515c771105011f4b40740ce53af8428d1c8ca20004"},
+    { file = "zope.interface-5.4.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:7df1e1c05304f26faa49fa752a8c690126cf98b40b91d54e6e9cc3b7d6ffe8b7" },
+    { file = "zope.interface-5.4.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:2c98384b254b37ce50eddd55db8d381a5c53b4c10ee66e1e7fe749824f894021" },
+    { file = "zope.interface-5.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:08f9636e99a9d5410181ba0729e0408d3d8748026ea938f3b970a0249daa8192" },
+    { file = "zope.interface-5.4.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0ea1d73b7c9dcbc5080bb8aaffb776f1c68e807767069b9ccdd06f27a161914a" },
+    { file = "zope.interface-5.4.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:273f158fabc5ea33cbc936da0ab3d4ba80ede5351babc4f577d768e057651531" },
+    { file = "zope.interface-5.4.0-cp27-cp27m-win32.whl", hash = "sha256:a1e6e96217a0f72e2b8629e271e1b280c6fa3fe6e59fa8f6701bec14e3354325" },
+    { file = "zope.interface-5.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:877473e675fdcc113c138813a5dd440da0769a2d81f4d86614e5d62b69497155" },
+    { file = "zope.interface-5.4.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f7ee479e96f7ee350db1cf24afa5685a5899e2b34992fb99e1f7c1b0b758d263" },
+    { file = "zope.interface-5.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:b0297b1e05fd128d26cc2460c810d42e205d16d76799526dfa8c8ccd50e74959" },
+    { file = "zope.interface-5.4.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:af310ec8335016b5e52cae60cda4a4f2a60a788cbb949a4fbea13d441aa5a09e" },
+    { file = "zope.interface-5.4.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:9a9845c4c6bb56e508651f005c4aeb0404e518c6f000d5a1123ab077ab769f5c" },
+    { file = "zope.interface-5.4.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:0b465ae0962d49c68aa9733ba92a001b2a0933c317780435f00be7ecb959c702" },
+    { file = "zope.interface-5.4.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:5dd9ca406499444f4c8299f803d4a14edf7890ecc595c8b1c7115c2342cadc5f" },
+    { file = "zope.interface-5.4.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:469e2407e0fe9880ac690a3666f03eb4c3c444411a5a5fddfdabc5d184a79f05" },
+    { file = "zope.interface-5.4.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:52de7fc6c21b419078008f697fd4103dbc763288b1406b4562554bd47514c004" },
+    { file = "zope.interface-5.4.0-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:3dd4952748521205697bc2802e4afac5ed4b02909bb799ba1fe239f77fd4e117" },
+    { file = "zope.interface-5.4.0-cp35-cp35m-win32.whl", hash = "sha256:dd93ea5c0c7f3e25335ab7d22a507b1dc43976e1345508f845efc573d3d779d8" },
+    { file = "zope.interface-5.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:3748fac0d0f6a304e674955ab1365d515993b3a0a865e16a11ec9d86fb307f63" },
+    { file = "zope.interface-5.4.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:66c0061c91b3b9cf542131148ef7ecbecb2690d48d1612ec386de9d36766058f" },
+    { file = "zope.interface-5.4.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:d0c1bc2fa9a7285719e5678584f6b92572a5b639d0e471bb8d4b650a1a910920" },
+    { file = "zope.interface-5.4.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2876246527c91e101184f63ccd1d716ec9c46519cc5f3d5375a3351c46467c46" },
+    { file = "zope.interface-5.4.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:334701327f37c47fa628fc8b8d28c7d7730ce7daaf4bda1efb741679c2b087fc" },
+    { file = "zope.interface-5.4.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:71aace0c42d53abe6fc7f726c5d3b60d90f3c5c055a447950ad6ea9cec2e37d9" },
+    { file = "zope.interface-5.4.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:5bb3489b4558e49ad2c5118137cfeaf59434f9737fa9c5deefc72d22c23822e2" },
+    { file = "zope.interface-5.4.0-cp36-cp36m-win32.whl", hash = "sha256:1c0e316c9add0db48a5b703833881351444398b04111188069a26a61cfb4df78" },
+    { file = "zope.interface-5.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f0c02cbb9691b7c91d5009108f975f8ffeab5dff8f26d62e21c493060eff2a1" },
+    { file = "zope.interface-5.4.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:7d97a4306898b05404a0dcdc32d9709b7d8832c0c542b861d9a826301719794e" },
+    { file = "zope.interface-5.4.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:867a5ad16892bf20e6c4ea2aab1971f45645ff3102ad29bd84c86027fa99997b" },
+    { file = "zope.interface-5.4.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5f931a1c21dfa7a9c573ec1f50a31135ccce84e32507c54e1ea404894c5eb96f" },
+    { file = "zope.interface-5.4.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:194d0bcb1374ac3e1e023961610dc8f2c78a0f5f634d0c737691e215569e640d" },
+    { file = "zope.interface-5.4.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:8270252effc60b9642b423189a2fe90eb6b59e87cbee54549db3f5562ff8d1b8" },
+    { file = "zope.interface-5.4.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:15e7d1f7a6ee16572e21e3576d2012b2778cbacf75eb4b7400be37455f5ca8bf" },
+    { file = "zope.interface-5.4.0-cp37-cp37m-win32.whl", hash = "sha256:8892f89999ffd992208754851e5a052f6b5db70a1e3f7d54b17c5211e37a98c7" },
+    { file = "zope.interface-5.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2e5a26f16503be6c826abca904e45f1a44ff275fdb7e9d1b75c10671c26f8b94" },
+    { file = "zope.interface-5.4.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:0f91b5b948686659a8e28b728ff5e74b1be6bf40cb04704453617e5f1e945ef3" },
+    { file = "zope.interface-5.4.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:4de4bc9b6d35c5af65b454d3e9bc98c50eb3960d5a3762c9438df57427134b8e" },
+    { file = "zope.interface-5.4.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bf68f4b2b6683e52bec69273562df15af352e5ed25d1b6641e7efddc5951d1a7" },
+    { file = "zope.interface-5.4.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:63b82bb63de7c821428d513607e84c6d97d58afd1fe2eb645030bdc185440120" },
+    { file = "zope.interface-5.4.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:db1fa631737dab9fa0b37f3979d8d2631e348c3b4e8325d6873c2541d0ae5a48" },
+    { file = "zope.interface-5.4.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:f44e517131a98f7a76696a7b21b164bcb85291cee106a23beccce454e1f433a4" },
+    { file = "zope.interface-5.4.0-cp38-cp38-win32.whl", hash = "sha256:a9506a7e80bcf6eacfff7f804c0ad5350c8c95b9010e4356a4b36f5322f09abb" },
+    { file = "zope.interface-5.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:3c02411a3b62668200910090a0dff17c0b25aaa36145082a5a6adf08fa281e54" },
+    { file = "zope.interface-5.4.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:0cee5187b60ed26d56eb2960136288ce91bcf61e2a9405660d271d1f122a69a4" },
+    { file = "zope.interface-5.4.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:a8156e6a7f5e2a0ff0c5b21d6bcb45145efece1909efcbbbf48c56f8da68221d" },
+    { file = "zope.interface-5.4.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:205e40ccde0f37496904572035deea747390a8b7dc65146d30b96e2dd1359a83" },
+    { file = "zope.interface-5.4.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:3f24df7124c323fceb53ff6168da70dbfbae1442b4f3da439cd441681f54fe25" },
+    { file = "zope.interface-5.4.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:5208ebd5152e040640518a77827bdfcc73773a15a33d6644015b763b9c9febc1" },
+    { file = "zope.interface-5.4.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:17776ecd3a1fdd2b2cd5373e5ef8b307162f581c693575ec62e7c5399d80794c" },
+    { file = "zope.interface-5.4.0-cp39-cp39-win32.whl", hash = "sha256:d4d9d6c1a455d4babd320203b918ccc7fcbefe308615c521062bc2ba1aa4d26e" },
+    { file = "zope.interface-5.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:0cba8477e300d64a11a9789ed40ee8932b59f9ee05f85276dbb4b59acee5dd09" },
+    { file = "zope.interface-5.4.0.tar.gz", hash = "sha256:5dba5f530fec3f0988d83b78cc591b58c0b6eb8431a85edd1569a0539a8a5a0e" },
 ]
diff --git a/pyproject.toml b/pyproject.toml
index ef14645..fd7574f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -26,17 +26,18 @@ packages = [
 "Bug Tracker" = "https://github.com/lewoudar/scalpel/issues"
 
 [tool.poetry.dependencies]
-python = "^3.6"
+python = "^3.6.2"
 parsel = "^1.5.2"
 attrs = "^19.3.0"
 fake-useragent = "^0.1.11"
-httpx = "^0.12.1"
 selenium = "^3.141.0"
 configuror = "^0.2.0"
 rfc3986 = { extras = ["idna"], version = "^1.4.0" }
 msgpack = "^1.0.0"
 gevent = { version = "^20.9.0", optional = true }
 trio = { version = "^0.17.0", optional = true }
+httpx = "^0.17.0"
+anyio = "^3.0.0"
 
 [tool.poetry.extras]
 gevent = ["gevent"]
@@ -50,13 +51,12 @@ flake8 = "^3.7.9"
 bandit = "^1.6.2"
 codecov = "^2.0.15"
 pytest-mock = "^2.0.0"
-respx = "^0.10.1"
-pytest-trio = "^0.6.0"
-mock = "^4.0.2"
 coverage = "^5.1"
+mock = "^4.0.3"
+mkdocs-material = "^7.0.5"
 mkdocs = "^1.1.2"
 mkautodoc = "^0.1.0"
-mkdocs-material = "^6.0.2"
+respx = "^0.16.3"
 
 [build-system]
 requires = ["poetry>=0.12"]
diff --git a/scalpel/__init__.py b/scalpel/__init__.py
index 42ea3ff..cf94235 100644
--- a/scalpel/__init__.py
+++ b/scalpel/__init__.py
@@ -1,10 +1,10 @@
-from .__version__ import __version__
+from .__version__ import __version__, version_info
 from .core.config import Configuration, Browser
 from .core.spider import State, SpiderStatistics
 from .core.message_pack import datetime_encoder, datetime_decoder
 
 __all__ = [
-    '__version__',
+    '__version__', 'version_info',
     # config
     'Configuration', 'Browser',
     # message pack
diff --git a/scalpel/__version__.py b/scalpel/__version__.py
index 97f677e..d1d2d4a 100644
--- a/scalpel/__version__.py
+++ b/scalpel/__version__.py
@@ -1,4 +1,4 @@
-__version__ = '0.1.0'
+__version__ = '0.1.2'
 
 
 def version_info():
diff --git a/scalpel/trionic/__init__.py b/scalpel/any_io/__init__.py
similarity index 92%
rename from scalpel/trionic/__init__.py
rename to scalpel/any_io/__init__.py
index 72e5bcd..bb04133 100644
--- a/scalpel/trionic/__init__.py
+++ b/scalpel/any_io/__init__.py
@@ -2,7 +2,7 @@
 from .response import StaticResponse, SeleniumResponse
 from .selenium_spider import SeleniumSpider
 from .static_spider import StaticSpider
-from .utils.queue import Queue
+from .queue import Queue
 
 __all__ = [
     # files
diff --git a/scalpel/trionic/files.py b/scalpel/any_io/files.py
similarity index 82%
rename from scalpel/trionic/files.py
rename to scalpel/any_io/files.py
index 3032bbe..4753213 100644
--- a/scalpel/trionic/files.py
+++ b/scalpel/any_io/files.py
@@ -1,14 +1,15 @@
-"""Utility async functions to read and write jl files"""
+"""Utility async functions to read and write mp files."""
 import logging
+from pathlib import Path
 from typing import Union, AsyncIterator, Any, Callable
 
+import anyio
 import msgpack
-import trio
 
 logger = logging.getLogger('scalpel')
 
 
-async def read_mp(filename: Union[str, trio.Path], decoder: Callable = None) -> AsyncIterator[Any]:
+async def read_mp(filename: Union[str, Path], decoder: Callable = None) -> AsyncIterator[Any]:
     """
     Reads a `msgpack` file generated by the spider when calling the `save_item` method.
 
@@ -19,9 +20,9 @@ async def read_mp(filename: Union[str, trio.Path], decoder: Callable = None) ->
 
     Usage:
 
-    ```
+    ```python
     from scalpel import datetime_decoder
-    from scalpel.trionic import read_mp
+    from scalpel.any_io import read_mp
 
     async for item in read_mp('file.mp', datetime_decoder):
         print(item)
@@ -32,7 +33,7 @@ async def read_mp(filename: Union[str, trio.Path], decoder: Callable = None) ->
         logger.exception(message)
         raise TypeError(message)
 
-    async with await trio.open_file(filename, 'rb') as f:
+    async with await anyio.open_file(filename, 'rb') as f:
         content = await f.read()
         unpacker = msgpack.Unpacker(None, max_buffer_size=len(content), object_hook=decoder)
         unpacker.feed(content)
@@ -41,7 +42,7 @@ async def read_mp(filename: Union[str, trio.Path], decoder: Callable = None) ->
             yield data
 
 
-async def write_mp(filename: Union[str, trio.Path], data: Any, mode: str = 'w', encoder: Callable = None) -> int:
+async def write_mp(filename: Union[str, Path], data: Any, mode: str = 'w', encoder: Callable = None) -> int:
     """
     Writes a `msgpack` file.
 
@@ -60,7 +61,7 @@ async def write_mp(filename: Union[str, trio.Path], data: Any, mode: str = 'w',
     ```
     from datetime import datetime
     from scalpel import datetime_encoder
-    from scalpel.trionic import write_mp
+    from scalpel.any_io import write_mp
 
     data = {'fruit': 'apple', 'date': datetime.utcnow()}
     length = await write_mp('file.mp', data, 'w', datetime_encoder)
@@ -77,7 +78,7 @@ async def write_mp(filename: Union[str, trio.Path], data: Any, mode: str = 'w',
         logger.exception(message)
         raise TypeError(message)
 
-    async with await trio.open_file(filename, f'{mode}b') as f:
+    async with await anyio.open_file(filename, f'{mode}b') as f:
         data_length = await f.write(msgpack.packb(data, default=encoder))
         logger.debug('writing %s bytes in file %s', data_length, filename)
         return data_length
diff --git a/scalpel/trionic/mixins.py b/scalpel/any_io/mixins.py
similarity index 84%
rename from scalpel/trionic/mixins.py
rename to scalpel/any_io/mixins.py
index b86f12a..d5d6bd6 100644
--- a/scalpel/trionic/mixins.py
+++ b/scalpel/any_io/mixins.py
@@ -1,7 +1,7 @@
 import logging
 from typing import Tuple
 
-import trio
+import anyio
 from selenium.common.exceptions import WebDriverException
 
 logger = logging.getLogger('scalpel')
@@ -15,9 +15,9 @@ def _get_resource(self, url: str, error_message: str = '') -> Tuple[bool, float]
         if not error_message:
             error_message = f'unable to get resource at {url}'
         try:
-            before = trio.current_time()
+            before = anyio.current_time()
             self._driver.get(url)
-            fetch_time = trio.current_time() - before
+            fetch_time = anyio.current_time() - before
         except WebDriverException:
             logger.exception(error_message)
             unreachable = True
diff --git a/scalpel/trionic/utils/queue.py b/scalpel/any_io/queue.py
similarity index 81%
rename from scalpel/trionic/utils/queue.py
rename to scalpel/any_io/queue.py
index 2383eaa..6514227 100644
--- a/scalpel/trionic/utils/queue.py
+++ b/scalpel/any_io/queue.py
@@ -1,9 +1,10 @@
-"""Implementation of a trio queue"""
+"""Implementation of an anyio queue."""
 import logging
-from typing import Union, List, Any
+from typing import Iterable, Any, Union
 
+import anyio
 import attr
-import trio
+from anyio.streams.memory import MemoryObjectSendStream, MemoryObjectReceiveStream
 
 logger = logging.getLogger('scalpel')
 
@@ -11,7 +12,7 @@
 @attr.s
 class Queue:
     """
-    An implementation of a trio queue with the capacity to tell of a task is done.
+    An implementation of an anyio queue with the capacity to tell that a task is done.
 
     **Parameters:**
 
@@ -19,16 +20,14 @@ class Queue:
     * **items:** A list of values used to initialize the queue.
 
     **N.B:** If you set `items`, be sure that the size of the queue is greater than `items` length, otherwise you will
-    have a `trio.WouldBlock` exception.
+    have a `anyio.WouldBlock` exception.
 
-    Usage:
-
-    ```
+    ```python
     import math
     import random
 
-    import trio
-    from scalpel.trionic import Queue
+    import anyio
+    from scalpel.any_io import Queue
 
     async def worker(name: str, queue: Queue) -> None:
         while True:
@@ -51,12 +50,12 @@ async def main():
                 queue.put_nowait(sleep_for)
 
             # Create three worker tasks to process the queue concurrently.
-            async with trio.open_nursery() as nursery:
+            async with anyio.create_task_group() as tg:
                 for i in range(3):
-                    nursery.start_soon(worker, f'worker-{i}', queue)
+                    tg.spawn(worker, f'worker-{i}', queue)
 
                 # Wait until the queue is fully processed.
-                before = trio.current_time()
+                before = anyio.current_time()
                 await queue.join()
                 total_slept_for = trio.current_time() - before
                 print('====')
@@ -64,22 +63,22 @@ async def main():
                 print(f'total expected sleep time: {total_sleep_time:.2f} seconds')
 
                 # We can end the nursery which will in turn end the tasks.
-                nursery.cancel_scope.cancel()
+                tg.cancel_scope.cancel()
 
 
-    trio.run(main)
+    anyio.run(main)
     ```
     """
     _size: Union[int, float] = attr.ib(default=1, validator=attr.validators.instance_of((int, float)))
-    _items: List[Any] = attr.ib(factory=list, validator=attr.validators.instance_of((list, set, tuple)))
-    _send_channel: trio.MemorySendChannel = attr.ib(init=False)
-    _receive_channel: trio.MemoryReceiveChannel = attr.ib(init=False)
+    _items: Iterable[Any] = attr.ib(factory=list, validator=attr.validators.instance_of((list, set, tuple)))
+    _send_channel: MemoryObjectSendStream = attr.ib(init=False)
+    _receive_channel: MemoryObjectReceiveStream = attr.ib(init=False)
     _tasks_in_progress: int = attr.ib(default=0, init=False)
-    _finished: trio.Event = attr.ib(factory=trio.Event, init=False)
+    _finished: anyio.Event = attr.ib(factory=anyio.Event, init=False)
 
     def __attrs_post_init__(self):
         logger.debug('initializing queue send and receive channels with a size of %s', self._size)
-        self._send_channel, self._receive_channel = trio.open_memory_channel(self._size)
+        self._send_channel, self._receive_channel = anyio.create_memory_object_stream(self._size)
         if self._items:
             logger.debug('trying to add items coming from list %s', self._items)
             for item in self._items:
@@ -112,7 +111,7 @@ async def put(self, item: Any) -> None:
         self._tasks_in_progress += 1
         logger.debug('number of tasks in progress is now: %s', self._tasks_in_progress)
         if self._finished.is_set():
-            self._finished = trio.Event()
+            self._finished = anyio.Event()
 
     def put_nowait(self, item: Any) -> None:
         logger.debug('trying to add %s to queue', item)
@@ -120,7 +119,7 @@ def put_nowait(self, item: Any) -> None:
         self._tasks_in_progress += 1
         logger.debug('number of tasks in progress is now: %s', self._tasks_in_progress)
         if self._finished.is_set():
-            self._finished = trio.Event()
+            self._finished = anyio.Event()
 
     async def get(self) -> Any:
         item = await self._receive_channel.receive()
diff --git a/scalpel/trionic/response.py b/scalpel/any_io/response.py
similarity index 94%
rename from scalpel/trionic/response.py
rename to scalpel/any_io/response.py
index 3f017c9..6b8b0a8 100644
--- a/scalpel/trionic/response.py
+++ b/scalpel/any_io/response.py
@@ -4,7 +4,7 @@
 import attr
 
 from scalpel.core.response import BaseStaticResponse, BaseSeleniumResponse
-from .utils.queue import Queue
+from .queue import Queue
 
 logger = logging.getLogger('scalpel')
 
@@ -48,7 +48,7 @@ class StaticResponse(CommonAttributes, FollowMixin, BaseStaticResponse):
 
     * **reachable_urls:** A `set` of urls already fetched.
     * **followed_urls:** A `set` of urls already followed by other `StaticResponse` objects.
-    * **queue:** The `scalpel.trionic.Queue` used by the spider to handle incoming urls.
+    * **queue:** The `scalpel.any_io.Queue` used by the spider to handle incoming urls.
     * **url:** An optional keyword parameter representing the current url where content was fetched.
     * **text:** An optional keyword parameter representing the content of the resource fetched. Note that if you set
     the `url` parameter, you **must** set this one.
@@ -58,7 +58,7 @@ class StaticResponse(CommonAttributes, FollowMixin, BaseStaticResponse):
     Usage:
 
     ```python
-    from scalpel.trionic import StaticResponse
+    from scalpel.any_io import StaticResponse
 
     response = StaticResponse(..., url='http://foo.com', text='<p>Hello world!</p>')
     print(response.css('p::text').get())  # 'Hello world!'
@@ -87,7 +87,7 @@ class SeleniumResponse(CommonAttributes, FollowMixin, BaseSeleniumResponse):
     Usage:
 
     ```
-    from scalpel.trionic import SeleniumResponse
+    from scalpel.any_io import SeleniumResponse
 
     response = SeleniumResponse(...)
     # We assume we have a page source like '<p>Hello world!</p>'
diff --git a/scalpel/trionic/robots.py b/scalpel/any_io/robots.py
similarity index 87%
rename from scalpel/trionic/robots.py
rename to scalpel/any_io/robots.py
index 2c24f58..5bef5da 100644
--- a/scalpel/trionic/robots.py
+++ b/scalpel/any_io/robots.py
@@ -1,10 +1,11 @@
 import logging
+from pathlib import Path
 from typing import Dict, Union, List
 from urllib.robotparser import RobotFileParser
 
+import anyio
 import attr
 import httpx
-import trio
 
 from scalpel.core.robots import RobotsMixin
 
@@ -15,8 +16,8 @@
 class RobotsAnalyzer(RobotsMixin):
     # order is important, _http_client can use the _user_agent info to instantiate itself
     _user_agent: str = attr.ib()
-    _robots_cache: trio.Path = attr.ib()
-    _robots_mapping: Dict[str, trio.Path] = attr.ib(factory=dict)
+    _robots_cache: Path = attr.ib()
+    _robots_mapping: Dict[str, Path] = attr.ib(factory=dict)
     _http_client: httpx.AsyncClient = attr.ib()
     _robots_parser: RobotFileParser = attr.ib(init=False, factory=RobotFileParser)
     _delay_mapping: Dict[str, Union[int, float]] = attr.ib(init=False, factory=dict)
@@ -28,14 +29,15 @@ def _get_default_client(self) -> httpx.AsyncClient:
         return httpx.AsyncClient(headers=headers)
 
     @staticmethod
-    async def _create_robots_file(robots_path: trio.Path, content: str) -> None:
+    async def _create_robots_file(robots_path: Path, content: str) -> None:
         logger.debug('creating robots file at path: %s', robots_path)
-        await robots_path.write_text(content)
+        async with await anyio.open_file(robots_path, 'w') as f:
+            await f.write(content)
 
     @staticmethod
-    async def _get_robots_lines(path: trio.Path) -> List[str]:
+    async def _get_robots_lines(path: Path) -> List[str]:
         logger.debug('getting robots file lines at path: %s', path)
-        async with await path.open() as f:
+        async with await anyio.open_file(path) as f:
             return await f.readlines()
 
     async def can_fetch(self, url: str) -> bool:
@@ -64,7 +66,7 @@ async def can_fetch(self, url: str) -> bool:
             else:
                 robot_path = self._robots_cache / host
                 await self._create_robots_file(robot_path, response.text)
-                self._robots_mapping[host] = await robot_path.absolute()
+                self._robots_mapping[host] = robot_path.absolute()
 
         robot_lines = await self._get_robots_lines(self._robots_mapping[host])
         self._robots_parser.parse(robot_lines)
diff --git a/scalpel/trionic/selenium_spider.py b/scalpel/any_io/selenium_spider.py
similarity index 96%
rename from scalpel/trionic/selenium_spider.py
rename to scalpel/any_io/selenium_spider.py
index 2b56989..38b989e 100644
--- a/scalpel/trionic/selenium_spider.py
+++ b/scalpel/any_io/selenium_spider.py
@@ -34,12 +34,12 @@ class SeleniumSpider(SeleniumGetMixin, StaticSpider, SeleniumDriverMixin):
     Usage:
 
     ```
-    from scalpel.trionic import SeleniumSpider, SeleniumResponse
+    from scalpel.any_io import SeleniumSpider, SeleniumResponse
 
     async def parse(spider: SeleniumSpider, response: SeleniumResponse) -> None:
         ...
 
-    spider = SeleniumSpider(urls=['http://example.com'], parse=parse)
+    spider = SeleniumSpider(urls=['https://example.com'], parse=parse)
     await spider.run()
     ```
     """
diff --git a/scalpel/trionic/static_spider.py b/scalpel/any_io/static_spider.py
similarity index 85%
rename from scalpel/trionic/static_spider.py
rename to scalpel/any_io/static_spider.py
index d9d0cdc..8c49cfe 100644
--- a/scalpel/trionic/static_spider.py
+++ b/scalpel/any_io/static_spider.py
@@ -2,18 +2,20 @@
 import math
 import platform
 from asyncio import iscoroutinefunction
+from pathlib import Path
 from typing import Callable, Optional, Any, Union
 
+import anyio
 import attr
 import httpx
-import trio
+from anyio.abc import TaskGroup
 from rfc3986 import uri_reference
 
 from scalpel.core.spider import Spider
 from .files import write_mp
 from .response import StaticResponse
 from .robots import RobotsAnalyzer
-from .utils.queue import Queue
+from .queue import Queue
 
 logger = logging.getLogger('scalpel')
 
@@ -38,21 +40,21 @@ class StaticSpider(Spider):
     Usage:
 
     ```
-    from scalpel.trionic import StaticSpider, StaticResponse
+    from scalpel.any_io import StaticSpider, StaticResponse
 
     async def parse(spider: StaticSpider, response: StaticResponse) -> None:
         ...
 
-    spider = StaticSpider(urls=['http://example.com'], parse=parse)
+    spider = StaticSpider(urls=['https://example.com'], parse=parse)
     await spider.run()
     ```
     """
     # order is important here, http_client must come before robots_analyzer since the latter used the former
-    _start_time: float = attr.ib(init=False, repr=False, factory=trio.current_time)
+    _start_time: float = attr.ib(init=False, repr=False, factory=anyio.current_time)
     _http_client: httpx.AsyncClient = attr.ib(init=False, repr=False)
     _robots_analyser: RobotsAnalyzer = attr.ib(init=False, repr=False)
     _fetch: Callable = attr.ib(init=False, repr=False)
-    _lock: trio.Lock = attr.ib(init=False, repr=False, factory=trio.Lock)
+    _lock: anyio.Lock = attr.ib(init=False, repr=False, factory=anyio.Lock)
     _queue: Queue = attr.ib(init=False, repr=False)
 
     def __attrs_post_init__(self):
@@ -75,7 +77,7 @@ def _get_robots_analyzer(self) -> RobotsAnalyzer:
         logger.debug('getting a default robots analyzer')
         return RobotsAnalyzer(
             http_client=self._http_client,
-            robots_cache=trio.Path(self.config.robots_cache_folder),
+            robots_cache=Path(self.config.robots_cache_folder),
             user_agent=self.config.user_agent
         )
 
@@ -97,7 +99,7 @@ def _get_static_response(
 
     def _is_url_already_processed(self, url: str) -> False:
         processed = False
-        if url in self.reachable_urls or url in self.unreachable_urls or url in self.robots_excluded_urls:
+        if url in [*self.reachable_urls, *self.unreachable_urls, *self.robots_excluded_urls]:
             logger.debug('url %s has already been processed', url)
             self._queue.task_done()
             processed = True
@@ -116,10 +118,10 @@ async def _handle_url(self, url: str) -> None:
             logger.debug('url %s is a file url so we attempt to read its content')
             file_path = ur.path[1:] if platform.system() == 'Windows' else ur.path
             try:
-                before = trio.current_time()
-                async with await trio.open_file(file_path) as f:
+                before = anyio.current_time()
+                async with await anyio.open_file(file_path) as f:
                     text = await f.read()
-                fetch_time = trio.current_time() - before
+                fetch_time = anyio.current_time() - before
             except OSError:
                 logger.exception('unable to open file %s', url)
                 self.unreachable_urls.add(url)
@@ -169,10 +171,10 @@ async def save_item(self, item: Any) -> None:
     async def _get_request_delay(self, url: str) -> Union[int, float]:
         if self.config.follow_robots_txt:
             return await self._robots_analyser.get_request_delay(url, self.config.request_delay)
-        await trio.sleep(0)  # checkpoint to ensure an async function in every case
+        await anyio.sleep(0)  # checkpoint to ensure an async function in every case
         return self.config.request_delay
 
-    async def worker(self, nursery: trio.Nursery) -> None:
+    async def worker(self, task_group: TaskGroup) -> None:
         while True:
             url = await self._queue.get()
             request_delay = await self._get_request_delay(url)
@@ -180,20 +182,22 @@ async def worker(self, nursery: trio.Nursery) -> None:
                 self.robots_excluded_urls.add(url)
                 self._queue.task_done()
                 continue
-            nursery.start_soon(self._handle_url, url)
-            await trio.sleep(request_delay)
+
+            task_group.start_soon(self._handle_url, url)
+            await anyio.sleep(request_delay)
 
     async def _cleanup(self) -> None:
         await self._http_client.aclose()
         await self._queue.close()
 
+    # noinspection PyAsyncCall
     async def run(self) -> None:
         """Runs the spider."""
-        async with trio.open_nursery() as nursery:
-            nursery.start_soon(self.worker, nursery)
+        async with anyio.create_task_group() as tg:
+            tg.start_soon(self.worker, tg)
             await self._queue.join()
             # at this point, all the urls were handled, so the only remaining task is the worker
-            nursery.cancel_scope.cancel()
+            tg.cancel_scope.cancel()
 
         await self._cleanup()
-        self._duration = trio.current_time() - self._start_time
+        self._duration = anyio.current_time() - self._start_time
diff --git a/scalpel/core/config.py b/scalpel/core/config.py
index 12cb91c..7b0c7ab 100644
--- a/scalpel/core/config.py
+++ b/scalpel/core/config.py
@@ -172,31 +172,45 @@ class Configuration:
     **Parameters:**
 
     * **min_request_delay:** The minimum delay to wait between two http requests. Defaults to 0s.
+
     * **max_request_delay:** The maximum delay to wait between two http requests. Defaults to 0s.
+
     * **fetch_timeout:** The timeout to fetch http resources using the inner
     [httpx](https://www.python-httpx.org/) client. Defaults to 5s.
+
     * **selenium_find_timeout:** The timeout for selenium driver to find an element in a page. Defaults to 10s.
+
     * **selenium_driver_log_file:** The file where the browser log debug messages. Defaults to *driver.log*.
     If you want to not create one, just pass `None`.
+
     * **selenium_browser:** The browser to use with the selenium spider. You can use the `Browser` enum to specify the
     value. Possible values are `Browser.FIREFOX` and `Browser.CHROME`. Defaults to `Browser.FIREFOX`.
+
     * **selenium_driver_executable_path:** The path to the browser driver. Defaults to *geckodriver* if
     `Browser.FIREFOX` is selected as *selenium_browser*, otherwise defaults to *chromedriver*.
+
     * **user_agent:** The user agent to fake. Mainly useful for the static spider. Defaults to a random value provided
     by [fake-useragent](https://pypi.org/project/fake-useragent/) and if it does not work, fallback to
     *Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36*
+
     * **follow_robots_txt:** Decide whether or not the spider should follow robots.txt rules on the website you are
     scraping. Defaults to `False`.
+
     * **robots_cache_folder:** A folder to cache content of different website robots.txt file to avoid retrieving
     it each time you want to analyze an html page. Default to the system temporary directory.
+
     * **backup_filename:** The filename were scraped items will be written. If you don't want one, simple pass `None`.
     Defaults to *backup-{uuid}.mp* where uuid is a `uuid.uuid4` string value. Note that values inserted in this file
     are streamed using `msgpack`. Look at the documentation to see how to use it.
+
     * **response_middlewares:** A list of callables that will be called with the callable that fetch the http resource.
     This parameter is only useful for the **static spider**. Defaults to an empty list.
+
     * **item_processors:** A list of callables that will be called with a scraped item. Defaults to an empty list.
+
     * **msgpack_encoder:** A callable that will be called when `msgpack` serializes an item.
     Defaults to `scalpel.datetime_encoder`.
+
     * **msgpack_decoder:** A callable that will be called when `msgpack` deserializes an item.
     Defaults to `scalpel.datetime_decoder`.
 
diff --git a/scalpel/core/spider.py b/scalpel/core/spider.py
index da340aa..a62ac0c 100644
--- a/scalpel/core/spider.py
+++ b/scalpel/core/spider.py
@@ -89,8 +89,9 @@ class Spider:
     urls: URLS = attr.ib(validator=url_validator)
     parse: Callable = attr.ib(validator=attr.validators.is_callable())
     _name: str = attr.ib(validator=attr.validators.instance_of(str))
-    _config: Configuration = attr.ib(factory=Configuration, validator=attr.validators.instance_of(Configuration),
-                                     repr=False)
+    _config: Configuration = attr.ib(
+        factory=Configuration, validator=attr.validators.instance_of(Configuration), repr=False
+    )
     _ignore_errors: bool = attr.ib(default=False, validator=attr.validators.instance_of(bool))
     reachable_urls: Set[str] = attr.ib(factory=set, init=False, repr=False)
     unreachable_urls: Set[str] = attr.ib(factory=set, init=False, repr=False)
diff --git a/scalpel/green/files.py b/scalpel/green/files.py
index f812e56..25a2499 100644
--- a/scalpel/green/files.py
+++ b/scalpel/green/files.py
@@ -1,4 +1,4 @@
-"""Utility functions to read and write jl files"""
+"""Utility functions to read and write mp files."""
 import logging
 from pathlib import Path
 from typing import Union, Iterator, Any, Callable
diff --git a/scalpel/green/static_spider.py b/scalpel/green/static_spider.py
index 1086b21..e01e9a5 100644
--- a/scalpel/green/static_spider.py
+++ b/scalpel/green/static_spider.py
@@ -98,7 +98,7 @@ def _get_static_response(
 
     def _is_url_already_processed(self, url: str) -> bool:
         processed = False
-        if url in self.reachable_urls or url in self.unreachable_urls or url in self.robots_excluded_urls:
+        if url in [*self.reachable_urls, *self.unreachable_urls, *self.robots_excluded_urls]:
             logger.debug('url %s has already been processed', url)
             processed = True
         return processed
diff --git a/setup.cfg b/setup.cfg
index ffb8c62..87877f4 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,5 @@
 [tool:pytest]
 testpaths = tests
-trio_mode = true
 
 [flake8]
 max-line-length = 120


Test patch:
diff --git a/scalpel/trionic/utils/__init__.py b/tests/any_io/__init__.py
similarity index 100%
rename from scalpel/trionic/utils/__init__.py
rename to tests/any_io/__init__.py
diff --git a/tests/any_io/conftest.py b/tests/any_io/conftest.py
new file mode 100644
index 0000000..3c3860c
--- /dev/null
+++ b/tests/any_io/conftest.py
@@ -0,0 +1,8 @@
+import pytest
+import respx
+
+
+@pytest.fixture()
+async def httpx_mock():
+    async with respx.mock(base_url='http://example.com') as _http_mock:
+        yield _http_mock
diff --git a/tests/trionic/test_files.py b/tests/any_io/test_files.py
similarity index 70%
rename from tests/trionic/test_files.py
rename to tests/any_io/test_files.py
index 0bf9534..4a5964b 100644
--- a/tests/trionic/test_files.py
+++ b/tests/any_io/test_files.py
@@ -1,9 +1,10 @@
 from datetime import datetime
 
 import pytest
-import trio
 
-from scalpel.trionic import read_mp, write_mp
+from scalpel.any_io.files import read_mp, write_mp
+
+pytestmark = pytest.mark.anyio
 
 
 class TestReadMp:
@@ -18,22 +19,24 @@ async def test_should_raise_error_when_decoder_is_not_callable(self, decoder):
 
         assert f'{decoder} is not callable' == str(exc_info.value)
 
-    async def test_should_return_python_objects_when_reading_file_without_custom_decoder(self, tmp_path,
-                                                                                         create_msgpack_file):
+    async def test_should_return_python_objects_when_reading_file_without_custom_decoder(
+            self, tmp_path, create_msgpack_file
+    ):
         given_data = [[1, 2], 'hello', {'fruit': 'apple'}]
         mp_file = tmp_path / 'data.mp'
         create_msgpack_file(mp_file, given_data)
 
-        for file in [f'{mp_file}', trio.Path(mp_file)]:
+        for file in [f'{mp_file}', mp_file]:
             assert [item async for item in read_mp(file)] == given_data
 
-    async def test_should_return_python_objects_when_reading_file_with_custom_decoder(self, tmp_path, decode_datetime,
-                                                                                      create_msgpack_file):
+    async def test_should_return_python_objects_when_reading_file_with_custom_decoder(
+            self, tmp_path, decode_datetime, create_msgpack_file
+    ):
         given_data = ['hello', datetime.now()]
         mp_file = tmp_path / 'data.mp'
         create_msgpack_file(mp_file, given_data)
 
-        for file in [str(mp_file), trio.Path(mp_file)]:
+        for file in [str(mp_file), mp_file]:
             assert [item async for item in read_mp(file, decoder=decode_datetime)] == given_data
 
 
@@ -55,27 +58,27 @@ async def test_should_raise_error_when_encoder_is_not_callable(self, encoder):
 
         assert f'{encoder} is not callable' == str(exc_info.value)
 
-    async def test_should_write_bytes_when_giving_content_in_write_mode_without_custom_encoder(self, trio_tmp_path):
+    async def test_should_write_bytes_when_giving_content_in_write_mode_without_custom_encoder(self, tmp_path):
         content = {'name': 'Kevin', 'fruit': 'water melon'}
-        mp_file = trio_tmp_path / 'data.mp'
+        mp_file = tmp_path / 'data.mp'
         length = await write_mp(mp_file, content, mode='w')
 
         assert length > 0
         assert [content] == [item async for item in read_mp(mp_file)]
 
-    async def test_should_write_bytes_when_giving_content_in_write_mode_with_custom_encoder(self, trio_tmp_path,
-                                                                                            encode_datetime,
-                                                                                            decode_datetime):
+    async def test_should_write_bytes_when_giving_content_in_write_mode_with_custom_encoder(
+            self, tmp_path, encode_datetime, decode_datetime
+    ):
         content = {'name': 'Kevin', 'date': datetime.now()}
-        mp_file = trio_tmp_path / 'data.mp'
+        mp_file = tmp_path / 'data.mp'
         length = await write_mp(f'{mp_file}', content, mode='w', encoder=encode_datetime)
 
         assert length > 0
         assert [content] == [item async for item in read_mp(mp_file, decoder=decode_datetime)]
 
-    async def test_should_write_bytes_when_giving_content_in_append_mode_without_custom_encoder(self, trio_tmp_path):
+    async def test_should_write_bytes_when_giving_content_in_append_mode_without_custom_encoder(self, tmp_path):
         content = ['foo', 4, {'fruit': 'water melon'}, [1, 4]]
-        mp_file = trio_tmp_path / 'data.mp'
+        mp_file = tmp_path / 'data.mp'
 
         for item in content:
             length = await write_mp(mp_file, item, mode='a')
@@ -83,11 +86,11 @@ async def test_should_write_bytes_when_giving_content_in_append_mode_without_cus
 
         assert content == [item async for item in read_mp(mp_file)]
 
-    async def test_should_write_bytes_when_giving_content_in_append_mode_with_custom_encoder(self, trio_tmp_path,
-                                                                                             encode_datetime,
-                                                                                             decode_datetime):
+    async def test_should_write_bytes_when_giving_content_in_append_mode_with_custom_encoder(
+            self, tmp_path, encode_datetime, decode_datetime
+    ):
         content = ['foo', datetime.now()]
-        mp_file = trio_tmp_path / 'data.mp'
+        mp_file = tmp_path / 'data.mp'
 
         for item in content:
             length = await write_mp(f'{mp_file}', item, mode='a', encoder=encode_datetime)
diff --git a/tests/trionic/utils/test_queue.py b/tests/any_io/test_queue.py
similarity index 70%
rename from tests/trionic/utils/test_queue.py
rename to tests/any_io/test_queue.py
index 3a4344f..49b3321 100644
--- a/tests/trionic/utils/test_queue.py
+++ b/tests/any_io/test_queue.py
@@ -1,55 +1,60 @@
 import math
 
+import anyio
 import pytest
-import trio
+from anyio.streams.memory import MemoryObjectSendStream, MemoryObjectReceiveStream
 
-from scalpel.trionic.utils.queue import Queue
+from scalpel.any_io.queue import Queue
 
+pytestmark = pytest.mark.anyio
 
+
+# since in the __init__ method we call anyio.create_event function which tries to guess
+# the async library, we must use async test functions even if we don't have async call in them
 class TestQueueInitialization:
 
-    def test_should_work_with_default_initialization(self):
+    async def test_should_work_with_default_initialization(self):
         queue = Queue()
         assert 1 == queue.maxsize
         assert 0 == queue.length
         assert [] == queue._items
         assert 0 == queue._tasks_in_progress
-        assert isinstance(queue._send_channel, trio.MemorySendChannel)
-        assert isinstance(queue._receive_channel, trio.MemoryReceiveChannel)
-        assert isinstance(queue._finished, trio.Event)
+        assert isinstance(queue._send_channel, MemoryObjectSendStream)
+        assert isinstance(queue._receive_channel, MemoryObjectReceiveStream)
+        assert isinstance(queue._finished, anyio.Event)
 
-    def test_should_work_when_initializing_buffer_size(self):
+    async def test_should_work_when_initializing_buffer_size(self):
         queue = Queue(size=3)
         assert 3 == queue.maxsize
         assert 0 == queue.length
 
-    def test_should_work_when_initializing_items(self):
+    async def test_should_work_when_initializing_items(self):
         items = [2, 'foo']
         queue = Queue(3, items=items)
         assert 3 == queue.maxsize
         assert items == queue._items
         assert len(items) == queue.length == queue._tasks_in_progress
 
-    def test_length_property_works_with_infinity_size(self):
+    async def test_length_property_works_with_infinity_size(self):
         queue = Queue(size=math.inf)
         assert 0 == queue.length
         assert queue.maxsize is math.inf
 
-    def test_should_work_when_initializing_with_size_and_items(self):
+    async def test_should_work_when_initializing_with_size_and_items(self):
         items = [2, 'foo']
         queue = Queue(size=3, items=items)
         assert 3 == queue.maxsize
         assert 2 == queue.length
         assert items == queue._items
 
-    def test_should_raise_error_when_size_is_negative(self):
+    async def test_should_raise_error_when_size_is_negative(self):
         with pytest.raises(ValueError) as exc_info:
             Queue(size=-1)
 
         assert 'size must not be less than 1 but you provide: -1' == str(exc_info.value)
 
-    def test_should_raise_error_when_size_is_less_than_items_length(self):
-        with pytest.raises(trio.WouldBlock):
+    async def test_should_raise_error_when_size_is_less_than_items_length(self):
+        with pytest.raises(anyio.WouldBlock):
             Queue(size=1, items=[2, 'foo'])
 
 
@@ -75,9 +80,10 @@ async def test_should_raise_would_block_error_when_buffer_is_full_and_put_nowait
         queue = Queue()
         queue.put_nowait(1)
 
-        with pytest.raises(trio.WouldBlock):
+        with pytest.raises(anyio.WouldBlock):
             queue.put_nowait(2)
 
+    # noinspection PyAsyncCall
     async def test_should_reset_event_when_event_is_set_and_put_method_is_called(self):
         queue = Queue()
         queue._finished.set()
@@ -85,6 +91,7 @@ async def test_should_reset_event_when_event_is_set_and_put_method_is_called(sel
 
         assert not queue._finished.is_set()
 
+    # noinspection PyAsyncCall
     async def test_should_reset_event_when_event_is_set_and_put_nowait_is_called(self):
         queue = Queue()
         queue._finished.set()
@@ -111,7 +118,7 @@ async def test_should_work_when_using_get_nowait_method(self):
     async def test_should_raise_would_block_error_when_using_get_nowait_on_empty_buffer(self):
         queue = Queue()
 
-        with pytest.raises(trio.WouldBlock):
+        with pytest.raises(anyio.WouldBlock):
             queue.get_nowait()
 
 
@@ -122,20 +129,20 @@ async def test_should_work_when_calling_close_method(self):
         queue = Queue()
         await queue.close()
 
-        with pytest.raises(trio.ClosedResourceError):
+        with pytest.raises(anyio.ClosedResourceError):
             await queue.put(2)
 
-        with pytest.raises(trio.ClosedResourceError):
+        with pytest.raises(anyio.ClosedResourceError):
             await queue.get()
 
     async def test_should_work_when_using_context_manager(self):
         async with Queue(size=1) as queue:
             queue.put_nowait(2)
 
-        with pytest.raises(trio.ClosedResourceError):
+        with pytest.raises(anyio.ClosedResourceError):
             queue.put_nowait(3)
 
-        with pytest.raises(trio.ClosedResourceError):
+        with pytest.raises(anyio.ClosedResourceError):
             queue.get_nowait()
 
 
@@ -155,14 +162,14 @@ async def test_should_work_when_using_task_done_and_join_methods(self):
             await queue.get()
             assert 1 == queue._tasks_in_progress
 
-            with trio.move_on_after(1) as cancel_scope:
+            with anyio.move_on_after(1) as cancel_scope:
                 await queue.join()
 
-            assert cancel_scope.cancelled_caught
+            assert cancel_scope.cancel_called
             queue.task_done()
             assert 0 == queue._tasks_in_progress
 
-            with trio.move_on_after(1) as cancel_scope:
+            with anyio.move_on_after(1) as cancel_scope:
                 await queue.join()
 
-            assert not cancel_scope.cancelled_caught
+            assert not cancel_scope.cancel_called
diff --git a/tests/trionic/test_response.py b/tests/any_io/test_response.py
similarity index 95%
rename from tests/trionic/test_response.py
rename to tests/any_io/test_response.py
index adc1f49..44f19cd 100644
--- a/tests/trionic/test_response.py
+++ b/tests/any_io/test_response.py
@@ -1,8 +1,10 @@
 import httpx
 import pytest
 
-from scalpel.trionic.response import StaticResponse, SeleniumResponse
-from scalpel.trionic.utils.queue import Queue
+from scalpel.any_io.response import StaticResponse, SeleniumResponse
+from scalpel.any_io.queue import Queue
+
+pytestmark = pytest.mark.anyio
 
 
 class TestStaticResponse:
diff --git a/tests/trionic/test_robots.py b/tests/any_io/test_robots.py
similarity index 50%
rename from tests/trionic/test_robots.py
rename to tests/any_io/test_robots.py
index 160e9b0..0c273a7 100644
--- a/tests/trionic/test_robots.py
+++ b/tests/any_io/test_robots.py
@@ -6,39 +6,41 @@
 import pytest
 import respx
 
-from scalpel.trionic.robots import RobotsAnalyzer
+from scalpel.any_io.robots import RobotsAnalyzer
 from tests.helpers import assert_dicts
 
+pytestmark = pytest.mark.anyio
+
 
 @pytest.fixture()
-def trio_analyzer(trio_tmp_path):
-    return RobotsAnalyzer(user_agent='Mozilla/5.0', robots_cache=trio_tmp_path)
+def anyio_analyzer(tmp_path):
+    return RobotsAnalyzer(user_agent='Mozilla/5.0', robots_cache=tmp_path)
 
 
 class TestRobotsAnalyzerInitialization:
     """Tests __init__ method"""
 
-    def test_should_correctly_instantiate_class_without_giving_httpx_response(self, trio_tmp_path):
-        analyzer = RobotsAnalyzer(user_agent='Mozilla/5.0', robots_cache=trio_tmp_path)
+    def test_should_correctly_instantiate_class_without_giving_httpx_response(self, tmp_path):
+        analyzer = RobotsAnalyzer(user_agent='Mozilla/5.0', robots_cache=tmp_path)
 
         assert 'Mozilla/5.0' == analyzer._user_agent
-        assert trio_tmp_path == analyzer._robots_cache
+        assert tmp_path == analyzer._robots_cache
         assert isinstance(analyzer._http_client, httpx.AsyncClient)
         assert 'Mozilla/5.0' == analyzer._http_client.headers['User-Agent']
         assert isinstance(analyzer._robots_parser, RobotFileParser)
         assert_dicts(analyzer._robots_mapping, {})
         assert_dicts(analyzer._delay_mapping, {})
 
-    def test_should_correctly_instantiate_class_with_httpx_response_passed_as_argument(self, trio_tmp_path):
+    def test_should_correctly_instantiate_class_with_httpx_response_passed_as_argument(self, tmp_path):
         http_client = httpx.AsyncClient(headers={'User-Agent': 'python-httpx'})
         analyzer = RobotsAnalyzer(
             user_agent='Mozilla/5.0',
-            robots_cache=trio_tmp_path,
+            robots_cache=tmp_path,
             http_client=http_client
         )
 
         assert 'Mozilla/5.0' == analyzer._user_agent
-        assert trio_tmp_path == analyzer._robots_cache
+        assert tmp_path == analyzer._robots_cache
         assert isinstance(analyzer._http_client, httpx.AsyncClient)
         assert 'python-httpx' == analyzer._http_client.headers['User-Agent']
         assert isinstance(analyzer._robots_parser, RobotFileParser)
@@ -49,158 +51,168 @@ def test_should_correctly_instantiate_class_with_httpx_response_passed_as_argume
 class TestCreateRobotsFile:
     """Tests method _create_robots_file"""
 
-    async def test_should_create_robots_file_given_host_and_content(self, trio_analyzer, robots_content):
-        robots_path = trio_analyzer._robots_cache / 'foo.com'
-        await trio_analyzer._create_robots_file(robots_path, robots_content)
+    async def test_should_create_robots_file_given_host_and_content(self, anyio_analyzer, robots_content):
+        robots_path = anyio_analyzer._robots_cache / 'foo.com'
+        await anyio_analyzer._create_robots_file(robots_path, robots_content)
 
-        assert await robots_path.read_text() == robots_content
+        assert robots_path.read_text() == robots_content
 
 
 class TestGetRobotsLines:
     """Tests method _get_robots_lines"""
 
-    async def test_should_return_robots_lines_when_giving_robots_path(self, trio_analyzer, robots_content):
+    async def test_should_return_robots_lines_when_giving_robots_path(self, anyio_analyzer, robots_content):
         lines = ['Hello word\n', 'Just a good day']
-        robots_path = trio_analyzer._robots_cache / 'foo.com'
-        await robots_path.write_text(''.join(lines))
+        robots_path = anyio_analyzer._robots_cache / 'foo.com'
+        robots_path.write_text(''.join(lines))
 
-        assert await trio_analyzer._get_robots_lines(robots_path) == lines
+        assert await anyio_analyzer._get_robots_lines(robots_path) == lines
 
 
 class TestCanFetch:
     """Tests method can_fetch"""
 
-    async def test_should_return_false_when_host_does_not_exist(self, httpx_mock, trio_analyzer):
-        httpx_mock.get('/robots.txt', content=httpx.ConnectTimeout())
-        assert await trio_analyzer.can_fetch('http://example.com/path') is False
+    async def test_should_return_false_when_host_does_not_exist(self, httpx_mock, anyio_analyzer):
+        httpx_mock.get('/robots.txt').mock(side_effect=httpx.ConnectTimeout)
+        assert await anyio_analyzer.can_fetch('http://example.com/path') is False
 
     @pytest.mark.parametrize('status_code', [401, 403])
-    async def test_should_return_false_when_robots_are_unauthorized_or_forbidden(self, trio_analyzer, httpx_mock,
-                                                                                 status_code):
-        httpx_mock.get('/robots.txt', status_code=status_code)
+    async def test_should_return_false_when_robots_are_unauthorized_or_forbidden(
+            self, anyio_analyzer, httpx_mock, status_code
+    ):
+        httpx_mock.get('/robots.txt') % status_code
 
-        assert await trio_analyzer.can_fetch('http://example.com/path') is False
+        assert await anyio_analyzer.can_fetch('http://example.com/path') is False
 
     @pytest.mark.parametrize('status_code', [404, 500])
-    async def test_should_return_true_when_other_http_errors_occurred(self, trio_analyzer, httpx_mock, status_code):
-        httpx_mock.get('/robots.txt', status_code=status_code)
+    async def test_should_return_true_when_other_http_errors_occurred(self, anyio_analyzer, httpx_mock, status_code):
+        httpx_mock.get('/robots.txt') % status_code
 
-        assert await trio_analyzer.can_fetch('http://example.com/path') is True
+        assert await anyio_analyzer.can_fetch('http://example.com/path') is True
 
     @pytest.mark.parametrize('url_path', ['photos', 'videos'])
-    async def test_should_return_false_when_requesting_forbidden_url(self, httpx_mock, trio_tmp_path, robots_content,
-                                                                     url_path):
-        analyzer = RobotsAnalyzer(user_agent='Googlebot', robots_cache=trio_tmp_path)
-        httpx_mock.get('/robots.txt', content=robots_content)
+    async def test_should_return_false_when_requesting_forbidden_url(
+            self, httpx_mock, tmp_path, robots_content, url_path
+    ):
+        analyzer = RobotsAnalyzer(user_agent='Googlebot', robots_cache=tmp_path)
+        httpx_mock.get('/robots.txt') % {'text': robots_content}
 
         assert await analyzer.can_fetch(f'http://example.com/{url_path}/1') is False
 
     @pytest.mark.parametrize('url_path', ['admin/', 'ajax/'])
-    async def test_should_return_true_when_requesting_allowed_url(self, httpx_mock, trio_tmp_path, robots_content,
-                                                                  url_path):
-        analyzer = RobotsAnalyzer(user_agent='Googlebot', robots_cache=trio_tmp_path)
-        httpx_mock.get('/robots.txt', content=robots_content)
+    async def test_should_return_true_when_requesting_allowed_url(
+            self, httpx_mock, tmp_path, robots_content, url_path
+    ):
+        analyzer = RobotsAnalyzer(user_agent='Googlebot', robots_cache=tmp_path)
+        httpx_mock.get('/robots.txt') % {'text': robots_content}
 
         assert await analyzer.can_fetch(f'http://example.com/{url_path}') is True
 
     @respx.mock
-    async def test_should_not_enter_if_block_if_robots_content_is_already_cached(self, trio_analyzer, trio_tmp_path,
-                                                                                 robots_content):
+    async def test_should_not_enter_if_block_if_robots_content_is_already_cached(
+            self, anyio_analyzer, tmp_path, robots_content
+    ):
         request = respx.get('http://example.com/robots.txt')
-        robots_path = trio_tmp_path / 'example.com'
-        await robots_path.write_text(robots_content)
-        trio_analyzer._robots_mapping['example.com'] = trio_tmp_path / 'example.com'
+        robots_path = tmp_path / 'example.com'
+        robots_path.write_text(robots_content)
+        anyio_analyzer._robots_mapping['example.com'] = tmp_path / 'example.com'
 
-        assert await trio_analyzer.can_fetch('http://example.com/path') is True
+        assert await anyio_analyzer.can_fetch('http://example.com/path') is True
         assert not request.called
 
 
 class TestGetRequestDelay:
     """Tests method get_request_delay"""
 
-    async def test_should_return_delay_if_it_is_in_internal_delay_mapping(self, mocker, trio_tmp_path):
+    async def test_should_return_delay_if_it_is_in_internal_delay_mapping(self, mocker, tmp_path):
         crawl_delay_mock = mocker.patch('urllib.robotparser.RobotFileParser.crawl_delay')
-        can_fetch_mock = mocker.patch('scalpel.trionic.robots.RobotsAnalyzer.can_fetch')
+        can_fetch_mock = mocker.patch('scalpel.any_io.robots.RobotsAnalyzer.can_fetch')
         delay = 2
-        analyzer = RobotsAnalyzer(robots_cache=trio_tmp_path, user_agent='Mozilla/5.0')
+        analyzer = RobotsAnalyzer(robots_cache=tmp_path, user_agent='Mozilla/5.0')
         analyzer._delay_mapping['example.com'] = delay
 
         assert await analyzer.get_request_delay('http://example.com/page/1', 0) == delay
         can_fetch_mock.assert_not_called()
         crawl_delay_mock.assert_not_called()
 
-    async def test_should_return_negative_value_when_url_is_not_fetchable(self, httpx_mock, trio_analyzer):
-        httpx_mock.get('/robots.txt', status_code=401)
+    async def test_should_return_negative_value_when_url_is_not_fetchable(self, httpx_mock, anyio_analyzer):
+        httpx_mock.get('/robots.txt') % 401
 
-        assert await trio_analyzer.get_request_delay('http://example.com/page/1', 0) == -1
+        assert await anyio_analyzer.get_request_delay('http://example.com/page/1', 0) == -1
 
-    async def test_should_call_can_fetch_only_one_time(self, mocker, trio_tmp_path):
+    async def test_should_call_can_fetch_only_one_time(self, mocker, tmp_path):
         url = 'http://example.com/page/1'
-        can_fetch_mock = mocker.patch('scalpel.trionic.robots.RobotsAnalyzer.can_fetch', new=mock.AsyncMock())
+        can_fetch_mock = mocker.patch('scalpel.any_io.robots.RobotsAnalyzer.can_fetch', new=mock.AsyncMock())
         can_fetch_mock.return_value = False
-        analyzer = RobotsAnalyzer(robots_cache=trio_tmp_path, user_agent='Mozilla/5.0')
+        analyzer = RobotsAnalyzer(robots_cache=tmp_path, user_agent='Mozilla/5.0')
 
         assert -1 == await analyzer.get_request_delay(url, 0)
         assert -1 == await analyzer.get_request_delay(url, 0)
         can_fetch_mock.assert_awaited_once_with(url)
 
-    async def test_should_return_crawl_delay_value_if_robots_txt_specified_it(self, httpx_mock, trio_analyzer,
-                                                                              robots_content):
+    async def test_should_return_crawl_delay_value_if_robots_txt_specified_it(
+            self, httpx_mock, anyio_analyzer, robots_content
+    ):
         new_content = robots_content + '\nCrawl-delay: 2'
-        httpx_mock.get('/robots.txt', content=new_content)
+        httpx_mock.get('/robots.txt') % {'text': new_content}
 
-        assert await trio_analyzer.get_request_delay('http://example.com/page/1', 0) == 2
+        assert await anyio_analyzer.get_request_delay('http://example.com/page/1', 0) == 2
 
-    async def test_should_call_crawl_delay_method_only_one_time(self, mocker, trio_analyzer, robots_content,
-                                                                httpx_mock):
-        httpx_mock.get('/robots.txt', content=robots_content)
+    async def test_should_call_crawl_delay_method_only_one_time(
+            self, mocker, anyio_analyzer, robots_content, httpx_mock
+    ):
+        httpx_mock.get('/robots.txt') % {'text': robots_content}
         crawl_delay_mock = mocker.patch('urllib.robotparser.RobotFileParser.crawl_delay', return_value=2)
 
-        assert await trio_analyzer.get_request_delay('http://example.com/page/1', 0) == 2
-        assert await trio_analyzer.get_request_delay('http://example.com/page/1', 0) == 2
+        assert await anyio_analyzer.get_request_delay('http://example.com/page/1', 0) == 2
+        assert await anyio_analyzer.get_request_delay('http://example.com/page/1', 0) == 2
         crawl_delay_mock.assert_called_once_with('*')
 
-    async def test_should_return_request_rate_if_robots_txt_specified_it(self, httpx_mock, trio_analyzer,
-                                                                         robots_content):
+    async def test_should_return_request_rate_if_robots_txt_specified_it(
+            self, httpx_mock, anyio_analyzer, robots_content
+    ):
         new_content = robots_content + '\nRequest-rate: 2/5'
-        httpx_mock.get('/robots.txt', content=new_content)
+        httpx_mock.get('/robots.txt') % {'text': new_content}
 
-        assert await trio_analyzer.get_request_delay('http://example.com/page/1', 0) == 2.5
+        assert await anyio_analyzer.get_request_delay('http://example.com/page/1', 0) == 2.5
 
-    async def test_should_call_request_rate_method_only_one_time(self, mocker, robots_content, trio_analyzer,
-                                                                 httpx_mock):
-        httpx_mock.get('/robots.txt', content=robots_content)
+    async def test_should_call_request_rate_method_only_one_time(
+            self, mocker, robots_content, anyio_analyzer, httpx_mock
+    ):
+        httpx_mock.get('/robots.txt') % {'text': robots_content}
         RequestRate = collections.namedtuple('RequestRate', 'requests seconds')
         request_rate = RequestRate(2, 5)
         request_rate_mock = mocker.patch('urllib.robotparser.RobotFileParser.request_rate', return_value=request_rate)
 
-        assert await trio_analyzer.get_request_delay('http://example.com/page/1', 0) == 2.5
-        assert await trio_analyzer.get_request_delay('http://example.com/page/1', 0) == 2.5
+        assert await anyio_analyzer.get_request_delay('http://example.com/page/1', 0) == 2.5
+        assert await anyio_analyzer.get_request_delay('http://example.com/page/1', 0) == 2.5
         request_rate_mock.assert_called_once_with('*')
 
-    async def test_should_return_given_delay_if_no_crawl_delay_or_request_rate_are_given(self, trio_analyzer,
-                                                                                         httpx_mock, robots_content):
-        httpx_mock.get('/robots.txt', content=robots_content)
+    async def test_should_return_given_delay_if_no_crawl_delay_or_request_rate_are_given(
+            self, anyio_analyzer, httpx_mock, robots_content
+    ):
+        httpx_mock.get('/robots.txt') % {'text': robots_content}
 
-        assert await trio_analyzer.get_request_delay('http://example.com/page/1', 3) == 3
+        assert await anyio_analyzer.get_request_delay('http://example.com/page/1', 3) == 3
 
-    async def test_should_return_cache_given_delay_if_compatible_url_is_called_twice(self, mocker, httpx_mock,
-                                                                                     robots_content, trio_analyzer):
+    async def test_should_return_cache_given_delay_if_compatible_url_is_called_twice(
+            self, mocker, httpx_mock, robots_content, anyio_analyzer
+    ):
         crawl_delay_mock = mocker.patch('urllib.robotparser.RobotFileParser.crawl_delay', return_value=None)
-        httpx_mock.get('/robots.txt', content=robots_content)
+        httpx_mock.get('/robots.txt') % {'text': robots_content}
 
-        assert await trio_analyzer.get_request_delay('http://example.com/page/1', 3) == 3
-        assert await trio_analyzer.get_request_delay('http://example.com/page/1', 3) == 3
+        assert await anyio_analyzer.get_request_delay('http://example.com/page/1', 3) == 3
+        assert await anyio_analyzer.get_request_delay('http://example.com/page/1', 3) == 3
         crawl_delay_mock.assert_called_once_with('*')
 
 
 class TestClose:
     """Tests method close"""
 
-    async def test_should_call_http_client_aclose_method(self, trio_tmp_path):
+    async def test_should_call_http_client_aclose_method(self, tmp_path):
         http_client_mock = mock.AsyncMock()
         analyzer = RobotsAnalyzer(
-            robots_cache=trio_tmp_path,
+            robots_cache=tmp_path,
             user_agent='Mozilla/5.0',
             http_client=http_client_mock,
         )
diff --git a/tests/trionic/test_selenium_spider.py b/tests/any_io/test_selenium_spider.py
similarity index 93%
rename from tests/trionic/test_selenium_spider.py
rename to tests/any_io/test_selenium_spider.py
index 391b38e..6a98563 100644
--- a/tests/trionic/test_selenium_spider.py
+++ b/tests/any_io/test_selenium_spider.py
@@ -3,17 +3,20 @@
 import httpx
 import pytest
 import respx
-import trio
+# noinspection PyProtectedMember
+from anyio._core._synchronization import Lock
 from selenium.common.exceptions import WebDriverException, NoSuchElementException
 from selenium.webdriver.remote.webdriver import WebDriver
 
+from scalpel.any_io.files import read_mp
+from scalpel.any_io.queue import Queue
+from scalpel.any_io.response import SeleniumResponse
+from scalpel.any_io.robots import RobotsAnalyzer
+from scalpel.any_io.selenium_spider import SeleniumSpider, StaticSpider
 from scalpel.core.config import Configuration, Browser
 from scalpel.core.message_pack import datetime_decoder
-from scalpel.trionic import read_mp
-from scalpel.trionic.response import SeleniumResponse
-from scalpel.trionic.robots import RobotsAnalyzer
-from scalpel.trionic.selenium_spider import SeleniumSpider, StaticSpider
-from scalpel.trionic.utils.queue import Queue
+
+pytestmark = pytest.mark.anyio
 
 
 class TestSeleniumSpider:
@@ -31,7 +34,7 @@ async def test_selenium_attributes_are_correctly_instantiated(self):
         assert isinstance(spider._http_client, httpx.AsyncClient)
         assert isinstance(spider._robots_analyser, RobotsAnalyzer)
         assert config == spider._config
-        assert isinstance(spider._lock, trio.Lock)
+        assert isinstance(spider._lock, Lock)
         assert isinstance(spider._queue, Queue)
 
         # cleanup
@@ -133,7 +136,7 @@ async def test_should_not_called_parse_method_if_url_is_not_accessible(self, moc
         async def parse(sel_spider, response):
             parse_args.extend([sel_spider, response])
 
-        respx.get(f'{url}/robots.txt', status_code=404)
+        respx.get(f'{url}/robots.txt') % 404
         mocker.patch('selenium.webdriver.remote.webdriver.WebDriver.get', side_effect=WebDriverException)
         config = Configuration(follow_robots_txt=True, selenium_driver_log_file=None)
         spider = SeleniumSpider(urls=[url], parse=parse, config=config)
@@ -147,7 +150,11 @@ async def parse(sel_spider, response):
         # cleanup
         await spider._cleanup()
 
-    async def test_should_fetch_content_when_giving_http_url(self, mocker):
+    # for an unknown reason asyncio timer on Windows does not work correctly which makes
+    # static_spider._total_fetch_time to be equal to 0.0 and therefore the test fails
+    # this si why the test is only run on trio backend
+    @pytest.mark.parametrize('anyio_backend', ['trio'])
+    async def test_should_fetch_content_when_giving_http_url(self, mocker, anyio_backend):
         parse_args = []
         url = 'http://foo.com'
 
@@ -266,7 +273,6 @@ async def test_should_save_correct_output_when_giving_file_url(self, page_1_file
         async for item in read_mp(backup_path, decoder=datetime_decoder):
             assert isinstance(item['date'], datetime)
             if item['author'] == 'Albert Einstein':
-                print(item)
                 albert_count += 1
 
         assert albert_count == 3
diff --git a/tests/trionic/test_static_spider.py b/tests/any_io/test_static_spider.py
similarity index 84%
rename from tests/trionic/test_static_spider.py
rename to tests/any_io/test_static_spider.py
index c325d69..deab5a4 100644
--- a/tests/trionic/test_static_spider.py
+++ b/tests/any_io/test_static_spider.py
@@ -1,23 +1,25 @@
 from datetime import datetime
 from pathlib import Path
 
+import anyio
 import httpx
 import pytest
 import respx
-import trio
 
+from scalpel.any_io.files import read_mp
+from scalpel.any_io.queue import Queue
+from scalpel.any_io.response import StaticResponse
+from scalpel.any_io.robots import RobotsAnalyzer
+from scalpel.any_io.static_spider import StaticSpider
 from scalpel.core.config import Configuration
 from scalpel.core.message_pack import datetime_decoder
 from scalpel.core.spider import SpiderStatistics
-from scalpel.trionic import read_mp
-from scalpel.trionic.response import StaticResponse
-from scalpel.trionic.robots import RobotsAnalyzer
-from scalpel.trionic.static_spider import StaticSpider
-from scalpel.trionic.utils.queue import Queue
+
+pytestmark = pytest.mark.anyio
 
 
 @pytest.fixture()
-async def trio_spider():
+async def anyio_spider():
     return StaticSpider(
         urls=['http://foo.com', 'http://bar.com', 'file:///home/kevin/page.html'], parse=lambda x, y: None
     )
@@ -31,7 +33,7 @@ async def test_specific_static_attributes_are_correctly_instantiated(self):
         spider = StaticSpider(urls=['http://foo.com'], parse=lambda x, y: None, config=config)
 
         assert config == spider._config
-        assert isinstance(spider._lock, trio.Lock)
+        assert isinstance(spider._lock, anyio.Lock)
         assert isinstance(spider._queue, Queue)
         assert isinstance(spider._start_time, float)
         assert isinstance(spider._http_client, httpx.AsyncClient)
@@ -40,10 +42,10 @@ async def test_specific_static_attributes_are_correctly_instantiated(self):
     # _fetch tests
 
     @respx.mock
-    async def test_fetch_method_returns_httpx_response(self, trio_spider):
+    async def test_fetch_method_returns_httpx_response(self, anyio_spider):
         url = 'http://foo.com'
-        respx.get('http://foo.com', content='content')
-        response = await trio_spider._fetch(url)
+        respx.get('http://foo.com') % {'text': 'content'}
+        response = await anyio_spider._fetch(url)
 
         assert 'content' == response.text
         assert 200 == response.status_code
@@ -77,14 +79,14 @@ async def wrapper(*args, **kwargs):
         ('', '', httpx.Response(200, request=httpx.Request('GET', 'http://foo.com')))
     ])
     async def test_should_return_static_response_when_giving_correct_input(
-            self, url, text, httpx_response, trio_spider
+            self, url, text, httpx_response, anyio_spider
     ):
-        static_response = trio_spider._get_static_response(url, text, httpx_response)
+        static_response = anyio_spider._get_static_response(url, text, httpx_response)
 
         assert isinstance(static_response, StaticResponse)
-        assert static_response._reachable_urls is trio_spider.reachable_urls
-        assert static_response._followed_urls is trio_spider.followed_urls
-        assert static_response._queue is trio_spider._queue
+        assert static_response._reachable_urls is anyio_spider.reachable_urls
+        assert static_response._followed_urls is anyio_spider.followed_urls
+        assert static_response._queue is anyio_spider._queue
         assert url == static_response._url
         assert text == static_response._text
         assert static_response._httpx_response is httpx_response
@@ -97,14 +99,14 @@ async def test_should_return_static_response_when_giving_correct_input(
         ({'http://foo.com'}, set(), set())
     ])
     async def test_should_do_nothing_if_url_is_already_present_in_one_url_set(
-            self, mocker, trio_spider, reachable_urls, unreachable_urls, robots_excluded_urls
+            self, mocker, anyio_spider, reachable_urls, unreachable_urls, robots_excluded_urls
     ):
         url = 'http://foo.com'
         logger_mock = mocker.patch('logging.Logger.debug')
-        trio_spider.reachable_urls = reachable_urls
-        trio_spider.unreachable_urls = unreachable_urls
-        trio_spider.robots_excluded_urls = robots_excluded_urls
-        await trio_spider._handle_url(url)
+        anyio_spider.reachable_urls = reachable_urls
+        anyio_spider.unreachable_urls = unreachable_urls
+        anyio_spider.robots_excluded_urls = robots_excluded_urls
+        await anyio_spider._handle_url(url)
 
         logger_mock.assert_any_call('url %s has already been processed', url)
 
@@ -153,7 +155,7 @@ async def test_should_not_called_parse_method_if_httpx_response_is_an_error_one(
         def parse(spider, response):
             parse_args.extend([spider, response])
 
-        respx.get(url, status_code=status_code)
+        respx.get(url) % status_code
         logger_mock = mocker.patch('logging.Logger.info')
         static_spider = StaticSpider(urls=[url], parse=parse)
         await static_spider._handle_url(url)
@@ -161,15 +163,19 @@ def parse(spider, response):
         assert [] == parse_args
         logger_mock.assert_any_call('fetching url %s returns an error with status code %s', url, status_code)
 
+    # for an unknown reason asyncio timer on Windows does not work correctly which makes
+    # static_spider._total_fetch_time to be equal to 0.0 and therefore the test fails
+    # this si why the test is only run on trio backend
     @respx.mock
-    async def test_should_fetch_content_when_giving_http_url(self):
+    @pytest.mark.parametrize('anyio_backend', ['trio'])
+    async def test_should_fetch_content_when_giving_http_url(self, anyio_backend):
         parse_args = []
         url = 'http://foo.com'
 
         async def parse(spider, response):
             parse_args.extend([spider, response])
 
-        respx.get(url, status_code=200, content='http content')
+        respx.get(url) % {'text': 'http content'}
         static_spider = StaticSpider(urls=[url], parse=parse)
         await static_spider._handle_url(url)
 
@@ -222,7 +228,7 @@ def processor_1(item):
             return item
 
         async def processor_2(item):
-            await trio.sleep(0)
+            await anyio.sleep(0)
             if 'banana' in item:
                 return
             return item
@@ -262,7 +268,7 @@ def processor(item):
     ])
     async def test_should_return_robots_txt_value_when_follow_robots_txt_is_true(self, robots_content, value):
         url = 'http://foo.com'
-        respx.get(f'{url}/robots.txt', content=f'User-agent:*\n{robots_content}')
+        respx.get(f'{url}/robots.txt') % {'text': f'User-agent:*\n{robots_content}'}
         static_spider = StaticSpider(urls=[url], parse=lambda x, y: None, config=Configuration(follow_robots_txt=True))
 
         assert value == await static_spider._get_request_delay(url)
@@ -270,7 +276,7 @@ async def test_should_return_robots_txt_value_when_follow_robots_txt_is_true(sel
     @respx.mock
     async def test_should_return_config_delay_when_follow_robots_txt_is_false(self):
         url = 'http://foo.com'
-        request = respx.get(f'{url}/robots.txt', content='User-agent:*\nDisallow: ')
+        request = respx.get(f'{url}/robots.txt') % {'text': 'User-agent:*\nDisallow: '}
         config = Configuration(min_request_delay=3, max_request_delay=3)
         static_spider = StaticSpider(urls=[url], parse=lambda x, y: None, config=config)
 
@@ -285,7 +291,7 @@ async def test_should_return_config_delay_when_follow_robots_txt_is_false(self):
     # to check the rest of the logic
     async def test_should_exclude_url_when_robots_txt_excludes_it(self):
         url = 'http://foo.com'
-        respx.get(f'{url}/robots.txt', status_code=401)
+        respx.get(f'{url}/robots.txt') % 401
 
         async def parse(*_) -> None:
             pass
@@ -295,11 +301,14 @@ async def parse(*_) -> None:
         assert static_spider.reachable_urls == set()
         assert static_spider.robots_excluded_urls == {url}
 
+    # trio is the only backend checked for the same reason explained above for the test
+    # test_should_fetch_content_when_giving_http_url
     @respx.mock
-    async def test_should_return_correct_statistics_after_running_spider(self):
+    @pytest.mark.parametrize('anyio_backend', ['trio'])
+    async def test_should_return_correct_statistics_after_running_spider(self, anyio_backend):
         url1 = 'http://foo.com'
-        respx.get(url1)
-        respx.get(f'{url1}/robots.txt', status_code=404)
+        respx.get(url1, path='/')
+        respx.get(f'{url1}', path='/robots.txt') % 404
 
         async def parse(*_) -> None:
             pass
@@ -370,13 +379,16 @@ async def test_should_work_with_file_url(self, page_1_file_url, tmp_path):
         assert stats.average_fetch_time == static_spider._total_fetch_time / stats.request_counter
         await self.common_assert(stats, backup_path)
 
+    # trio is the only backend checked for the same reason explained above for the test
+    # test_should_fetch_content_when_giving_http_url
     @respx.mock
-    async def test_should_work_with_http_url(self, page_content, tmp_path):
+    @pytest.mark.parametrize('anyio_backend', ['trio'])
+    async def test_should_work_with_http_url(self, page_content, tmp_path, anyio_backend):
         url = 'http://quotes.com'
-        respx.get(f'{url}/robots.txt', status_code=404)
-        respx.get(url, content=page_content('page1.html'))
+        respx.get(url, path='/robots.txt') % 404
+        respx.get(url, path='/') % {'html': page_content('page1.html')}
         for i in range(2, 4):
-            respx.get(f'{url}/page{i}.html', content=page_content(f'page{i}.html'))
+            respx.get(url, path=f'/page{i}.html') % {'html': page_content(f'page{i}.html')}
 
         backup_path = tmp_path / 'backup.mp'
         config = Configuration(
diff --git a/tests/core/test_response.py b/tests/core/test_response.py
index f20dd52..6a56bd2 100644
--- a/tests/core/test_response.py
+++ b/tests/core/test_response.py
@@ -41,7 +41,7 @@ def test_should_validate_properties_when_passing_httpx_response(self):
         response = BaseStaticResponse(httpx_response=httpx_response)
 
         assert url == response.url
-        assert_dicts(headers, response.headers)
+        assert_dicts({**headers, 'content-length': '11'}, response.headers)
         assert_dicts({'name': 'John'}, response.cookies)
         assert content == response.content
         assert content.decode() == response.text
diff --git a/tests/green/conftest.py b/tests/green/conftest.py
index 4f6a73b..3def39f 100644
--- a/tests/green/conftest.py
+++ b/tests/green/conftest.py
@@ -5,5 +5,5 @@
 @pytest.fixture()
 def httpx_mock():
     """respx mock object"""
-    with respx.HTTPXMock(base_url='http://example.com') as _httpx_mock:
+    with respx.mock(base_url='http://example.com') as _httpx_mock:
         yield _httpx_mock
diff --git a/tests/green/test_robots.py b/tests/green/test_robots.py
index 7a22811..04b73aa 100644
--- a/tests/green/test_robots.py
+++ b/tests/green/test_robots.py
@@ -70,40 +70,42 @@ class TestCanFetch:
     """Tests method can_fetch"""
 
     def test_should_return_false_when_host_does_not_exist(self, green_analyzer, httpx_mock):
-        httpx_mock.get('/robots.txt', content=httpx.ConnectTimeout())
+        httpx_mock.get('/robots.txt').mock(side_effect=httpx.ConnectTimeout)
 
         assert green_analyzer.can_fetch('http://example.com/path') is False
 
     @pytest.mark.parametrize('status_code', [401, 403])
-    def test_should_return_false_when_robots_are_unauthorized_or_forbidden(self, green_analyzer, httpx_mock,
-                                                                           status_code):
-        httpx_mock.get('/robots.txt', status_code=status_code)
+    def test_should_return_false_when_robots_are_unauthorized_or_forbidden(
+            self, green_analyzer, httpx_mock, status_code
+    ):
+        httpx_mock.get('/robots.txt') % status_code
 
         assert green_analyzer.can_fetch('http://example.com/') is False
 
     @pytest.mark.parametrize('status_code', [404, 500])
     def test_should_return_true_when_other_http_errors_occurred(self, green_analyzer, httpx_mock, status_code):
-        httpx_mock.get('/robots.txt', status_code=status_code)
+        httpx_mock.get('/robots.txt') % status_code
 
         assert green_analyzer.can_fetch('http://example.com/') is True
 
     @pytest.mark.parametrize('url_path', ['photos', 'videos'])
     def test_should_return_false_when_requesting_forbidden_url(self, httpx_mock, tmp_path, robots_content, url_path):
         analyzer = RobotsAnalyzer(user_agent='Googlebot', robots_cache=tmp_path)
-        httpx_mock.get('/robots.txt', content=robots_content)
+        httpx_mock.get('/robots.txt') % {'text': robots_content}
 
         assert analyzer.can_fetch(f'http://example.com/{url_path}/1') is False
 
     @pytest.mark.parametrize('url_path', ['admin/', 'ajax/'])
     def test_should_return_true_when_requesting_allowed_url(self, httpx_mock, tmp_path, robots_content, url_path):
         analyzer = RobotsAnalyzer(user_agent='Googlebot', robots_cache=tmp_path)
-        httpx_mock.get('/robots.txt', content=robots_content)
+        httpx_mock.get('/robots.txt') % {'text': robots_content}
 
         assert analyzer.can_fetch(f'http://example.com/{url_path}') is True
 
     @respx.mock
-    def test_should_not_enter_if_block_if_robots_content_is_already_cached(self, green_analyzer, tmp_path,
-                                                                           robots_content):
+    def test_should_not_enter_if_block_if_robots_content_is_already_cached(
+            self, green_analyzer, tmp_path, robots_content
+    ):
         request = respx.get('http://example.com/robots.txt')
         robots_path = tmp_path / 'example.com'
         robots_path.write_text(robots_content)
@@ -128,7 +130,7 @@ def test_should_return_delay_if_it_is_in_internal_delay_mapping(self, mocker, tm
         crawl_delay_mock.assert_not_called()
 
     def test_should_return_negative_value_when_url_is_not_fetchable(self, green_analyzer, httpx_mock):
-        httpx_mock.get('/robots.txt', status_code=401)
+        httpx_mock.get('/robots.txt') % 401
 
         assert -1 == green_analyzer.get_request_delay('http://example.com/page/1', 0)
 
@@ -141,15 +143,16 @@ def test_should_call_can_fetch_only_one_time(self, mocker, tmp_path):
         assert -1 == analyzer.get_request_delay(url, 0)
         can_fetch_mock.assert_called_once_with(url)
 
-    def test_should_return_crawl_delay_value_if_robots_txt_specified_it(self, green_analyzer, httpx_mock,
-                                                                        robots_content):
+    def test_should_return_crawl_delay_value_if_robots_txt_specified_it(
+            self, green_analyzer, httpx_mock, robots_content
+    ):
         new_content = robots_content + '\nCrawl-delay: 2'
-        httpx_mock.get('/robots.txt', content=new_content)
+        httpx_mock.get('/robots.txt') % {'text': new_content}
 
         assert 2 == green_analyzer.get_request_delay('http://example.com/page/1', 0)
 
     def test_should_call_crawl_delay_method_only_one_time(self, mocker, green_analyzer, robots_content, httpx_mock):
-        httpx_mock.get('/robots.txt', content=robots_content)
+        httpx_mock.get('/robots.txt') % {'text': robots_content}
         crawl_delay_mock = mocker.patch('urllib.robotparser.RobotFileParser.crawl_delay', return_value=2)
 
         assert 2 == green_analyzer.get_request_delay('http://example.com/page/1', 0)
@@ -158,12 +161,12 @@ def test_should_call_crawl_delay_method_only_one_time(self, mocker, green_analyz
 
     def test_should_return_request_rate_if_robots_txt_specified_it(self, green_analyzer, httpx_mock, robots_content):
         new_content = robots_content + '\nRequest-rate: 2/5'
-        httpx_mock.get('/robots.txt', content=new_content)
+        httpx_mock.get('/robots.txt') % {'text': new_content}
 
         assert 2.5 == green_analyzer.get_request_delay('http://example.com/page/1', 0)
 
     def test_should_call_request_rate_method_only_one_time(self, mocker, green_analyzer, httpx_mock, robots_content):
-        httpx_mock.get('/robots.txt', content=robots_content)
+        httpx_mock.get('/robots.txt') % {'text': robots_content}
         RequestRate = collections.namedtuple('RequestRate', 'requests seconds')
         request_rate = RequestRate(2, 5)
         request_rate_mock = mocker.patch('urllib.robotparser.RobotFileParser.request_rate', return_value=request_rate)
@@ -172,16 +175,18 @@ def test_should_call_request_rate_method_only_one_time(self, mocker, green_analy
         assert 2.5 == green_analyzer.get_request_delay('http://example.com/page/1', 0)
         request_rate_mock.assert_called_once_with('*')
 
-    def test_should_return_given_delay_if_no_crawl_delay_or_request_rate_are_given(self, green_analyzer, httpx_mock,
-                                                                                   robots_content):
-        httpx_mock.get('/robots.txt', content=robots_content)
+    def test_should_return_given_delay_if_no_crawl_delay_or_request_rate_are_given(
+            self, green_analyzer, httpx_mock, robots_content
+    ):
+        httpx_mock.get('/robots.txt') % {'text': robots_content}
 
         assert 3 == green_analyzer.get_request_delay('http://example.com/page/1', 3)
 
-    def test_should_return_cache_given_delay_if_compatible_url_is_called_twice(self, mocker, green_analyzer, httpx_mock,
-                                                                               robots_content):
+    def test_should_return_cache_given_delay_if_compatible_url_is_called_twice(
+            self, mocker, green_analyzer, httpx_mock, robots_content
+    ):
         crawl_delay_mock = mocker.patch('urllib.robotparser.RobotFileParser.crawl_delay', return_value=None)
-        httpx_mock.get('/robots.txt', content=robots_content)
+        httpx_mock.get('/robots.txt') % {'text': robots_content}
 
         assert 3 == green_analyzer.get_request_delay('http://example.com/page/1', 3)
         assert 3 == green_analyzer.get_request_delay('http://example.com/page/1', 3)
diff --git a/tests/green/test_selenium_spider.py b/tests/green/test_selenium_spider.py
index 70a94e9..2e30b43 100644
--- a/tests/green/test_selenium_spider.py
+++ b/tests/green/test_selenium_spider.py
@@ -136,7 +136,7 @@ def test_should_not_called_parse_method_if_url_is_forbidden_by_robots_txt(self,
         def parse(sel_spider, response):
             parse_args.extend([sel_spider, response])
 
-        respx.get(f'{url}/robots.txt', status_code=401)
+        respx.get(f'{url}/robots.txt') % 401
         logger_mock = mocker.patch('logging.Logger.info')
         config = Configuration(follow_robots_txt=True, selenium_driver_log_file=None)
         spider = SeleniumSpider(urls=[url], parse=parse, config=config)
@@ -159,7 +159,7 @@ def test_should_not_called_parse_method_if_url_is_not_accessible(self, mocker):
         def parse(sel_spider, response):
             parse_args.extend([sel_spider, response])
 
-        respx.get(f'{url}/robots.txt', status_code=404)
+        respx.get(f'{url}/robots.txt') % 404
         mocker.patch('selenium.webdriver.remote.webdriver.WebDriver.get', side_effect=WebDriverException)
         config = Configuration(follow_robots_txt=True, selenium_driver_log_file=None)
         spider = SeleniumSpider(urls=[url], parse=parse, config=config)
@@ -181,7 +181,7 @@ def test_should_fetch_content_when_giving_http_url(self, mocker):
         def parse(sel_spider, response):
             parse_args.extend([sel_spider, response])
 
-        respx.get(f'{url}/robots.txt', status_code=404)
+        respx.get(f'{url}/robots.txt') % 404
         mocker.patch('selenium.webdriver.remote.webdriver.WebDriver.get')
         mocker.patch('selenium.webdriver.remote.webdriver.WebDriver.current_window_handle', 'handle')
         config = Configuration(follow_robots_txt=True, selenium_driver_log_file=None)
diff --git a/tests/green/test_static_spider.py b/tests/green/test_static_spider.py
index f83be56..76a4d42 100644
--- a/tests/green/test_static_spider.py
+++ b/tests/green/test_static_spider.py
@@ -46,7 +46,7 @@ def test_specific_static_attributes_are_correctly_instantiated(self):
     @respx.mock
     def test_fetch_method_returns_httpx_response(self, green_spider):
         url = 'http://foo.com'
-        respx.get('http://foo.com', content='content')
+        respx.get('http://foo.com') % {'text': 'content'}
         response = green_spider._fetch(url)
 
         assert 'content' == response.text
@@ -156,7 +156,7 @@ def test_should_not_called_parse_method_if_httpx_response_is_an_error_one(self,
         def parse(spider, response):
             parse_args.extend([spider, response])
 
-        respx.get(url, status_code=status_code)
+        respx.get(url) % status_code
         logger_mock = mocker.patch('logging.Logger.info')
         static_spider = StaticSpider(urls=[url], parse=parse)
         static_spider._handle_url(url)
@@ -172,7 +172,7 @@ def test_should_not_called_parse_method_if_url_is_forbidden_by_robots_txt(self,
         def parse(spider, response):
             parse_args.extend([spider, response])
 
-        respx.get(f'{url}/robots.txt', status_code=401)
+        respx.get(f'{url}/robots.txt') % 401
         logger_mock = mocker.patch('logging.Logger.info')
         static_spider = StaticSpider(urls=[url], parse=parse, config=Configuration(follow_robots_txt=True))
         static_spider._handle_url(url)
@@ -191,7 +191,7 @@ def test_should_fetch_content_when_giving_http_url(self):
         def parse(spider, response):
             parse_args.extend([spider, response])
 
-        respx.get(url, status_code=200, content='http content')
+        respx.get(url) % {'status_code': 200, 'text': 'http content'}
         static_spider = StaticSpider(urls=[url], parse=parse)
         static_spider._handle_url(url)
 
@@ -306,9 +306,9 @@ def processor(item):
     def test_should_return_correct_statistics_after_running_spider(self):
         url1 = 'http://foo.com'
         url2 = 'http://bar.com'
-        respx.get(url1)
-        respx.get(f'{url1}/robots.txt', status_code=404)
-        respx.get(f'{url2}/robots.txt', status_code=401)
+        respx.get(url1, path='/')
+        respx.get(url1, path='/robots.txt') % 404
+        respx.get(f'{url2}/robots.txt') % 401
 
         config = Configuration(follow_robots_txt=True)
         static_spider = StaticSpider(urls=[url1, url2], parse=lambda x, y: None, config=config)
@@ -380,10 +380,10 @@ def test_should_work_with_file_url(self, page_1_file_url, tmp_path):
     @respx.mock
     def test_should_work_with_http_url(self, page_content, tmp_path):
         url = 'http://quotes.com'
-        respx.get(f'{url}/robots.txt', status_code=404)
-        respx.get(url, content=page_content('page1.html'))
+        respx.get(url, path='/robots.txt') % 404
+        respx.get(url, path='/') % {'html': page_content('page1.html')}
         for i in range(2, 4):
-            respx.get(f'{url}/page{i}.html', content=page_content(f'page{i}.html'))
+            respx.get(url, path=f'/page{i}.html') % {'html': page_content(f'page{i}.html')}
 
         backup_path = tmp_path / 'backup.mp'
         config = Configuration(
diff --git a/tests/trionic/__init__.py b/tests/trionic/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/trionic/conftest.py b/tests/trionic/conftest.py
deleted file mode 100644
index 6a5e90c..0000000
--- a/tests/trionic/conftest.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import pytest
-import respx
-import trio
-
-
-@pytest.fixture()
-def trio_tmp_path(tmp_path):
-    """Trio tmp_path"""
-    return trio.Path(tmp_path)
-
-
-@pytest.fixture()
-async def httpx_mock():
-    async with respx.HTTPXMock(base_url='http://example.com') as _http_mock:
-        yield _http_mock
diff --git a/tests/trionic/utils/__init__.py b/tests/trionic/utils/__init__.py
deleted file mode 100644
index e69de29..0000000