summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Falcão <gabrielfalcao@users.noreply.github.com>2021-05-24 22:42:48 +0200
committerGitHub <noreply@github.com>2021-05-24 22:42:48 +0200
commit98faed6255315338392529fada5afd241bc0d35e (patch)
tree56614c42f220721ae2d9bf22083f86a503166676
parentca84d393f8d3e3220cca36981ebf10fb1c024d40 (diff)
downloadhttpretty-98faed6255315338392529fada5afd241bc0d35e.tar.gz
Add "Guides" section to docs (#432)
* install extension for asciinema in rst * update makefile * add guides to docs
-rw-r--r--Makefile7
-rw-r--r--README.rst1
-rw-r--r--development.txt3
-rw-r--r--docs/source/_static/guide-callback-regex-ipdb.py20
-rw-r--r--docs/source/_static/read-timeout.py39
-rw-r--r--docs/source/_static/regex-example.py14
-rw-r--r--docs/source/_static/tmplun_dcms-ascii.cast235
-rw-r--r--docs/source/conf.py2
-rw-r--r--docs/source/guides.rst119
-rw-r--r--docs/source/index.rst1
10 files changed, 438 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 4d9173d..d3d337d 100644
--- a/Makefile
+++ b/Makefile
@@ -17,8 +17,11 @@ $(VENV): # creates $(VENV) folder if does not exist
python3 -mvenv $(VENV)
$(VENV)/bin/pip install -U pip setuptools
-setup $(VENV)/bin/sphinx-build $(VENV)/bin/twine $(VENV)/bin/nosetests $(VENV)/bin/pytest $(VENV)/bin/python $(VENV)/bin/pip: # installs latest pip
+$(VENV)/bin/sphinx-build $(VENV)/bin/twine $(VENV)/bin/nosetests $(VENV)/bin/pytest $(VENV)/bin/python $(VENV)/bin/pip: # installs latest pip
test -e $(VENV)/bin/pip || make $(VENV)
+ $(MAKE) setup
+
+setup: | $(VENV)/bin/pip
$(VENV)/bin/pip install -r development.txt
$(VENV)/bin/pip install -e .
@@ -30,7 +33,7 @@ tdd: $(VENV)/bin/nosetests # runs all tests
$(VENV)/bin/nosetests tests --with-watch --cover-erase
# Install dependencies
-dependencies: | $(VENV)/bin/nosetests
+dependencies: | setup $(VENV)/bin/nosetests
# runs unit tests
unit: $(VENV)/bin/nosetests # runs only unit tests
diff --git a/README.rst b/README.rst
index 9818cb7..75c5c27 100644
--- a/README.rst
+++ b/README.rst
@@ -160,3 +160,4 @@ but some folks made remarkable contributions and deserve extra credit:
- Matt Luongo ~> `@mhluongo <https://github.com/mhluongo>`_
- Steve Pulec ~> `@spulec <https://github.com/spulec>`_
- Miro Hrončok ~> `@hroncok <https://github.com/hroncok>`_
+ Mario Jonke ~> `@mariojonke <https://github.com/mariojonke>`_
diff --git a/development.txt b/development.txt
index aa6cab6..08eeb36 100644
--- a/development.txt
+++ b/development.txt
@@ -19,7 +19,7 @@ rednose>=1.3.0
requests-toolbelt>=0.9.1
singledispatch>=3.4.0.3
sphinx-rtd-theme>=0.5.2
-sphinx>=4.0.1
+sphinx>=4.0.2
sure>=1.4.11
tornado>=6.0.4
tox>=3.14.5
@@ -28,3 +28,4 @@ urllib3>=1.25.8
boto3>=1.17.72
ndg-httpsclient>=0.5.1
pytest-mypy==0.8.1
+sphinxcontrib.asciinema==0.3.2
diff --git a/docs/source/_static/guide-callback-regex-ipdb.py b/docs/source/_static/guide-callback-regex-ipdb.py
new file mode 100644
index 0000000..9ca9f9a
--- /dev/null
+++ b/docs/source/_static/guide-callback-regex-ipdb.py
@@ -0,0 +1,20 @@
+import re
+import json
+import requests
+from httpretty import httprettified, HTTPretty
+
+
+@httprettified(verbose=True, allow_net_connect=False)
+def test_basic_body():
+
+ def my_callback(request, url, headers):
+ body = {}
+ import ipdb;ipdb.set_trace()
+ return (200, headers, json.dumps(body))
+
+ # Match any url via the regular expression
+ HTTPretty.register_uri(HTTPretty.GET, re.compile(r'.*'), body=my_callback)
+ HTTPretty.register_uri(HTTPretty.POST, re.compile(r'.*'), body=my_callback)
+
+ # will trigger ipdb
+ response = requests.post('https://test.com', data=json.dumps({'hello': 'world'}))
diff --git a/docs/source/_static/read-timeout.py b/docs/source/_static/read-timeout.py
new file mode 100644
index 0000000..59e668e
--- /dev/null
+++ b/docs/source/_static/read-timeout.py
@@ -0,0 +1,39 @@
+import requests, time
+from threading import Event
+
+from httpretty import httprettified
+from httpretty import HTTPretty
+
+
+@httprettified(allow_net_connect=False)
+def test_read_timeout():
+ event = Event()
+ wait_seconds = 10
+ connect_timeout = 0.1
+ read_timeout = 0.1
+
+ def my_callback(request, url, headers):
+ event.wait(wait_seconds)
+ return 200, headers, "Received"
+
+ HTTPretty.register_uri(
+ HTTPretty.GET, "http://example.com",
+ body=my_callback
+ )
+
+ requested_at = time.time()
+ try:
+ requests.get(
+ "http://example.com",
+ timeout=(connect_timeout, read_timeout))
+ except requests.exceptions.ReadTimeout:
+ pass
+
+ event_set_at = time.time()
+ event.set()
+
+ now = time.time()
+
+ assert now - event_set_at < 0.2
+ total_duration = now - requested_at
+ assert total_duration < 0.2
diff --git a/docs/source/_static/regex-example.py b/docs/source/_static/regex-example.py
new file mode 100644
index 0000000..72fc3fe
--- /dev/null
+++ b/docs/source/_static/regex-example.py
@@ -0,0 +1,14 @@
+import re
+import requests
+import httpretty
+
+
+@httpretty.activate(allow_net_connect=False, verbose=True)
+def test_regex():
+ httpretty.register_uri(httpretty.GET, re.compile(r'.*'), status=418)
+
+ response1 = requests.get('http://foo.com')
+ assert response1.status_code == 418
+
+ response2 = requests.get('http://test.com')
+ assert response2.status_code == 418
diff --git a/docs/source/_static/tmplun_dcms-ascii.cast b/docs/source/_static/tmplun_dcms-ascii.cast
new file mode 100644
index 0000000..6e26bca
--- /dev/null
+++ b/docs/source/_static/tmplun_dcms-ascii.cast
@@ -0,0 +1,235 @@
+{"version": 2, "width": 115, "height": 30, "timestamp": 1621882710, "env": {"SHELL": "/usr/local/bin/bash", "TERM": "xterm-256color"}}
+[1.115441, "o", "HTTPretty $ "]
+[1.648012, "o", "."]
+[1.67985, "o", "v"]
+[1.767955, "o", "e"]
+[2.045646, "o", "nv/"]
+[2.888016, "o", "b"]
+[2.960179, "o", "i"]
+[3.046058, "o", "n/"]
+[4.703758, "o", "o"]
+[5.007876, "o", "\b\u001b[K"]
+[5.183768, "o", "n"]
+[5.249014, "o", "o"]
+[5.286233, "o", "s"]
+[5.423938, "o", "e"]
+[5.553841, "o", "\u0007tests"]
+[6.562148, "o", " "]
+[6.680246, "o", "d"]
+[6.791965, "o", "o"]
+[6.880409, "o", "cs/"]
+[7.533022, "o", "s"]
+[7.596079, "o", "ource/"]
+[7.636732, "o", "o"]
+[7.728134, "o", "u"]
+[8.176255, "o", "\b\u001b[K"]
+[8.321962, "o", "\b\u001b[K"]
+[8.463491, "o", "_"]
+[8.584109, "o", "s"]
+[8.727909, "o", "t"]
+[8.780703, "o", "atic/"]
+[9.403611, "o", "\u0007"]
+[10.393067, "o", "\r\n"]
+[10.393402, "o", "__pycache__/ guide-callback-regex-ipdb.py logo.svg\r\nHTTPretty $ .venv/bin/nosetests docs/source/_static/"]
+[10.517051, "o", "\r\n"]
+[10.517371, "o", "__pycache__/ guide-callback-regex-ipdb.py logo.svg\r\nHTTPretty $ .venv/bin/nosetests docs/source/_static/"]
+[11.423948, "o", "g"]
+[11.532343, "o", "uide-callback-regex-ipdb.py "]
+[14.504165, "o", "\r\n"]
+[16.477912, "o", "#190 guide-callback-regex-ipdb.test_basic_body ... "]
+[18.01153, "o", "> \u001b[0;32m/Users/gabrielfalcao/projects/personal/HTTPretty/docs/source/_static/guide-callback-regex-ipdb.py\u001b[0m(13)\u001b[0;36mmy_callback\u001b[0;34m()\u001b[0m\r\n\u001b[0;32m 12 \u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mipdb\u001b[0m\u001b[0;34m;\u001b[0m\u001b[0mipdb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset_trace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[0m\u001b[0;32m---> 13 \u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m200\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mheaders\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mjson\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdumps\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbody\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[0m\u001b[0;32m 14 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[0m\r\n"]
+[18.014165, "o", "\u001b[?1l"]
+[18.014537, "o", "\u001b[6n"]
+[18.030527, "o", "\u001b[?2004h\u001b[?25l\u001b[0m\u001b[?7l\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[6D\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[18.071481, "o", "\u001b[?25l\u001b[?7l\u001b[6D\u001b[0;38;5;28mipdb> \u001b[0m\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\u001b[0m \b\u001b[22A\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[21.666012, "o", "\u001b[?25l\u001b[?7l\u001b[0ml\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[21.879456, "o", "\u001b[?25l\u001b[?7l\u001b[7D\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[0ml\u001b[7D\u001b[0m\r\r\n\u001b[J\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h\u001b[?2004l"]
+[21.882208, "o", "\u001b[1;32m 8 \u001b[0m\u001b[0;32mdef\u001b[0m \u001b[0mtest_basic_body\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[1;32m 9 \u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[1;32m 10 \u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmy_callback\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrequest\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mheaders\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[1;32m 11 \u001b[0m \u001b[0mbody\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[1;32m 12 \u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mipdb\u001b[0m\u001b[0;34m;\u001b[0m\u001b[0mipdb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset_trace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[0;32m---> 13 \u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m200\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mheaders\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mjson\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdumps\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbody\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[0m\u001b[1;32m 14 \u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[1;32m 15 \u001b[0m \u001b[0;31m# Match any url via the regular expression\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[1;32m 16 \u001b[0m \u001b[0mHTTPrett"]
+[21.882467, "o", "y\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mregister_uri\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mHTTPretty\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mGET\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mre\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcompile\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mr'.*'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbody\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmy_callback\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[1;32m 17 \u001b[0m \u001b[0mHTTPretty\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mregister_uri\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mHTTPretty\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mPOST\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mre\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcompile\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mr'.*'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbody\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmy_callback\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\u001b[1;32m 18 \u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\r\n\r\n"]
+[21.883476, "o", "\u001b[?1l"]
+[21.883604, "o", "\u001b[6n"]
+[21.887032, "o", "\u001b[?2004h\u001b[?25l\u001b[0m\u001b[?7l\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[6D\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[21.892331, "o", "\u001b[?25l\u001b[?7l\u001b[6D\u001b[0;38;5;28mipdb> \u001b[0m\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\u001b[0m \b\u001b[9A\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[22.81778, "o", "\u001b[?25l\u001b[?7l\u001b[0mp\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[22.969469, "o", "\u001b[?25l\u001b[?7l\u001b[0mp\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[23.181313, "o", "\u001b[?25l\u001b[?7l\u001b[C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[23.322972, "o", "\u001b[?25l\u001b[?7l\u001b[0mr\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[23.378349, "o", "\u001b[?25l\u001b[?7l\u001b[0me\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[23.544925, "o", "\u001b[?25l\u001b[?7l\u001b[0mq\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[23.665954, "o", "\u001b[?25l\u001b[?7l\u001b[0mu\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[23.741902, "o", "\u001b[?25l\u001b[?7l\u001b[0me\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[23.879494, "o", "\u001b[?25l\u001b[?7l\u001b[0ms\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[24.000226, "o", "\u001b[?25l\u001b[?7l\u001b[0mt\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[24.365902, "o", "\u001b[?25l\u001b[?7l\u001b[16D\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[0mpp request\u001b[16D\u001b[0m\r\r\n\u001b[J\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h\u001b[?2004l"]
+[24.367405, "o", "<HTTPrettyRequest(\"POST\", \"https://test.com/\", headers={'Host': 'test.com', 'User-Agent': 'python-requests/2.25.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '18'}, body=18)>\r\n"]
+[24.368531, "o", "\u001b[?1l"]
+[24.368635, "o", "\u001b[6n"]
+[24.371795, "o", "\u001b[?2004h\u001b[?25l\u001b[0m\u001b[?7l\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[6D\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[24.376988, "o", "\u001b[?25l\u001b[?7l\u001b[6D\u001b[0;38;5;28mipdb> \u001b[0m\r\r\n\r\r\n\r\r\n\r\r\n\r\r\n\u001b[0m \b\u001b[5A\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[27.359342, "o", "\u001b[?25l\u001b[?7l\u001b[0mpp request\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[27.82273, "o", "\u001b[?25l\u001b[?7l\u001b[0m.\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[28.255766, "o", "\u001b[?25l\u001b[?7l\u001b[0mh\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[28.313307, "o", "\u001b[?25l\u001b[?7l\u001b[0me\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[28.405472, "o", "\u001b[?25l\u001b[?7l\u001b[0ma\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[28.850422, "o", "\u001b[?25l\u001b[?7l\u001b[0md\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[28.912138, "o", "\u001b[?25l\u001b[?7l\u001b[0me\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[29.015229, "o", "\u001b[?25l\u001b[?7l\u001b[0mr\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[29.112081, "o", "\u001b[?25l\u001b[?7l\u001b[0ms\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[29.429921, "o", "\u001b[?25l\u001b[?7l\u001b[24D\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[0mpp request.headers\u001b[24D\u001b[0m\r\r\n\u001b[J\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h\u001b[?2004l"]
+[29.431801, "o", "<http.client.HTTPMessage object at 0x112326a30>\r\n"]
+[29.433016, "o", "\u001b[?1l"]
+[29.433238, "o", "\u001b[6n"]
+[29.436901, "o", "\u001b[?2004h\u001b[?25l\u001b[0m\u001b[?7l\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[6D\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[29.444544, "o", "\u001b[?25l\u001b[?7l\u001b[6D\u001b[0;38;5;28mipdb> \u001b[0m\r\r\n\r\r\n\r\r\n\u001b[0m \b\u001b[3A\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[30.156471, "o", "\u001b[?25l\u001b[?7l\u001b[0mpp request.headers\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[30.608228, "o", "\u001b[?25l\u001b[?7l\u001b[7D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[30.765725, "o", "\u001b[?25l\u001b[?7l\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[30.902549, "o", "\u001b[?25l\u001b[?7l\u001b[7D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[31.381908, "o", "\u001b[?25l\u001b[?7l\u001b[0mdrequest.headers\u001b[15D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[31.510943, "o", "\u001b[?25l\u001b[?7l\u001b[0mirequest.headers\u001b[15D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[31.57281, "o", "\u001b[?25l\u001b[?7l\u001b[0mcrequest.headers\u001b[15D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[31.725778, "o", "\u001b[?25l\u001b[?7l\u001b[0mtrequest.headers\u001b[15D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[31.890771, "o", "\u001b[?25l\u001b[?7l\u001b[0m(request.headers\u001b[15D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[32.215385, "o", "\u001b[?25l\u001b[?7l\u001b[15C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[32.495352, "o", "\u001b[?25l\u001b[?7l\u001b[0m)\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[32.983501, "o", "\u001b[?25l\u001b[?7l\u001b[30D\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[0mpp dict(request.headers)\u001b[30D\u001b[0m\r\r\n\u001b[J\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h\u001b[?2004l"]
+[32.98525, "o", "{'Accept': '*/*',\r\n 'Accept-Encoding': 'gzip, deflate',\r\n 'Connection': 'keep-alive',\r\n 'Content-Length': '18',\r\n 'Host': 'test.com',\r\n 'User-Agent': 'python-requests/2.25.1'}\r\n"]
+[32.986518, "o", "\u001b[?1l"]
+[32.986746, "o", "\u001b[6n"]
+[32.990263, "o", "\u001b[?2004h\u001b[?25l\u001b[0m\u001b[?7l\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[6D\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[32.996419, "o", "\u001b[?25l\u001b[?7l\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[35.671881, "o", "\u001b[?25l\u001b[?7l\u001b[0mp\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[35.856772, "o", "\u001b[?25l\u001b[?7l\u001b[0mp\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[37.215658, "o", "\u001b[?25l\u001b[?7l\u001b[C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[37.693648, "o", "\u001b[?25l\u001b[?7l\u001b[0mr\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[37.758114, "o", "\u001b[?25l\u001b[?7l\u001b[0me\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[38.110067, "o", "\u001b[?25l\u001b[?7l\b\u001b[0m\u001b[K\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[38.247765, "o", "\u001b[?25l\u001b[?7l\u001b[2D\u001b[0m\u001b[K\u001b[C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[38.397251, "o", "\u001b[?25l\u001b[?7l\u001b[0mh\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[38.444177, "o", "\u001b[?25l\u001b[?7l\u001b[0me\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[38.561504, "o", "\u001b[?25l\u001b[?7l\u001b[0ma\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[38.790802, "o", "\u001b[?25l\u001b[?7l\u001b[0md\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[38.926065, "o", "\u001b[?25l\u001b[?7l\u001b[0me\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[39.04009, "o", "\u001b[?25l\u001b[?7l\u001b[0mr\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[39.140742, "o", "\u001b[?25l\u001b[?7l\u001b[0ms\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[39.437672, "o", "\u001b[?25l\u001b[?7l\u001b[C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[39.886449, "o", "\u001b[?25l\u001b[?7l\u001b[17D\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[0mpp headers\u001b[16D\u001b[0m\r\r\n\u001b[J\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h\u001b[?2004l"]
+[39.888255, "o", "{'connection': 'close',\r\n 'date': 'Mon, 24 May 2021 18:58:47 GMT',\r\n 'server': 'Python/HTTPretty',\r\n 'status': 200}\r\n"]
+[39.890098, "o", "\u001b[?1l"]
+[39.890285, "o", "\u001b[6n"]
+[39.894169, "o", "\u001b[?2004h\u001b[?25l\u001b[0m\u001b[?7l\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[6D\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[39.898533, "o", "\u001b[?25l\u001b[?7l\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[45.717659, "o", "\u001b[?25l\u001b[?7l\u001b[0mh\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[45.733999, "o", "\u001b[?25l\u001b[?7l\u001b[0me\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[45.856076, "o", "\u001b[?25l\u001b[?7l\u001b[0ma\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[45.94174, "o", "\u001b[?25l\u001b[?7l\u001b[0md\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[46.030913, "o", "\u001b[?25l\u001b[?7l\u001b[0me\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[46.118401, "o", "\u001b[?25l\u001b[?7l\u001b[0mr\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[46.205205, "o", "\u001b[?25l\u001b[?7l\u001b[0ms\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[46.470445, "o", "\u001b[?25l\u001b[?7l\u001b[0m[\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[46.589064, "o", "\u001b[?25l\u001b[?7l\u001b[0m]\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[46.916657, "o", "\u001b[?25l\u001b[?7l\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[47.326705, "o", "\u001b[?25l\u001b[?7l\u001b[0m'']\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[47.354431, "o", "\u001b[?25l\u001b[?7l\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[47.384967, "o", "\u001b[?25l\u001b[?7l\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[47.47368, "o", "\u001b[?25l\u001b[?7l\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[48.062051, "o", "\u001b[?25l\u001b[?7l\u001b[C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[48.345923, "o", "\u001b[?25l\u001b[?7l\u001b[0mC']\u001b[2D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[48.59897, "o", "\u001b[?25l\u001b[?7l\u001b[0mo']\u001b[2D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[48.663284, "o", "\u001b[?25l\u001b[?7l\u001b[0mn']\u001b[2D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[48.750459, "o", "\u001b[?25l\u001b[?7l\u001b[0mt']\u001b[2D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[48.809164, "o", "\u001b[?25l\u001b[?7l\u001b[0me']\u001b[2D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[48.888522, "o", "\u001b[?25l\u001b[?7l\u001b[0mn']\u001b[2D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[48.949883, "o", "\u001b[?25l\u001b[?7l\u001b[0mt']\u001b[2D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[49.088369, "o", "\u001b[?25l\u001b[?7l\u001b[0m-']\u001b[2D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[49.265468, "o", "\u001b[?25l\u001b[?7l\u001b[0mT']\u001b[2D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[49.450521, "o", "\u001b[?25l\u001b[?7l\u001b[0my']\u001b[2D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[49.516735, "o", "\u001b[?25l\u001b[?7l\u001b[0mp']\u001b[2D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[49.662079, "o", "\u001b[?25l\u001b[?7l\u001b[0me']\u001b[2D\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[50.01415, "o", "\u001b[?25l\u001b[?7l\u001b[2C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[50.444668, "o", "\u001b[?25l\u001b[?7l\u001b[C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[50.506213, "o", "\u001b[?25l\u001b[?7l\u001b[0m=\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[50.566841, "o", "\u001b[?25l\u001b[?7l\u001b[C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[51.624083, "o", "\u001b[?25l\u001b[?7l\u001b[0m'\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[51.970211, "o", "\u001b[?25l\u001b[?7l\u001b[0m'\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[52.078158, "o", "\u001b[?25l\u001b[?7l\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[52.254808, "o", "\u001b[?25l\u001b[?7l\u001b[0ma'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[52.349951, "o", "\u001b[?25l\u001b[?7l\u001b[0mp'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[52.515528, "o", "\u001b[?25l\u001b[?7l\u001b[0mp'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[52.629864, "o", "\u001b[?25l\u001b[?7l\u001b[0ml'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[52.8266, "o", "\u001b[?25l\u001b[?7l\u001b[0mi'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[52.912236, "o", "\u001b[?25l\u001b[?7l\u001b[0mc'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[52.96185, "o", "\u001b[?25l\u001b[?7l\u001b[0ma'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[53.099131, "o", "\u001b[?25l\u001b[?7l\u001b[0mt'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[53.185005, "o", "\u001b[?25l\u001b[?7l\u001b[0mio'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[53.254551, "o", "\u001b[?25l\u001b[?7l\u001b[0mn'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[53.439432, "o", "\u001b[?25l\u001b[?7l\u001b[0m/'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[53.67937, "o", "\u001b[?25l\u001b[?7l\u001b[0mj'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[53.792533, "o", "\u001b[?25l\u001b[?7l\u001b[0ms'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[53.843024, "o", "\u001b[?25l\u001b[?7l\u001b[0mo'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[53.905637, "o", "\u001b[?25l\u001b[?7l\u001b[0mn'\b\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[54.32111, "o", "\u001b[?25l\u001b[?7l\u001b[49D\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[0mheaders['Content-Type'] = 'application/json'\u001b[50D\u001b[0m\r\r\n\u001b[J\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h\u001b[?2004l"]
+[54.323453, "o", "\u001b[?1l"]
+[54.323703, "o", "\u001b[6n"]
+[54.32769, "o", "\u001b[?2004h\u001b[?25l\u001b[0m\u001b[?7l\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[6D\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[54.33208, "o", "\u001b[?25l\u001b[?7l\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[55.431101, "o", "\u001b[?25l\u001b[?7l\u001b[0mb\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[55.502203, "o", "\u001b[?25l\u001b[?7l\u001b[0mo\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[55.577597, "o", "\u001b[?25l\u001b[?7l\u001b[0md\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[55.702116, "o", "\u001b[?25l\u001b[?7l\u001b[0my\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[55.887196, "o", "\u001b[?25l\u001b[?7l\u001b[10D\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[0mbody\u001b[10D\u001b[0m\r\r\n\u001b[J\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[55.887473, "o", "\u001b[?2004l"]
+[55.888628, "o", "{}\r\n"]
+[55.889744, "o", "\u001b[?1l"]
+[55.889857, "o", "\u001b[6n"]
+[55.893146, "o", "\u001b[?2004h\u001b[?25l\u001b[0m\u001b[?7l\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[6D\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[55.89828, "o", "\u001b[?25l\u001b[?7l\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[56.247068, "o", "\u001b[?25l\u001b[?7l\u001b[0mb\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[56.319912, "o", "\u001b[?25l\u001b[?7l\u001b[0mo\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[56.448876, "o", "\u001b[?25l\u001b[?7l\u001b[0md\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[56.521946, "o", "\u001b[?25l\u001b[?7l\u001b[0my\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[56.870316, "o", "\u001b[?25l\u001b[?7l\u001b[0m=\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[57.286911, "o", "\u001b[?25l\u001b[?7l\b\u001b[0m\u001b[K\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[57.598176, "o", "\u001b[?25l\u001b[?7l\u001b[0m[\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[58.044934, "o", "\u001b[?25l\u001b[?7l\u001b[0m\"\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[58.398262, "o", "\u001b[?25l\u001b[?7l\u001b[0mo\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[58.568438, "o", "\u001b[?25l\u001b[?7l\u001b[0mo\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[58.814278, "o", "\u001b[?25l\u001b[?7l\b\u001b[0m\u001b[K\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[58.98533, "o", "\u001b[?25l\u001b[?7l\b\u001b[0m\u001b[K\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[59.183923, "o", "\u001b[?25l\u001b[?7l\b\u001b[0m\u001b[K\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[60.874043, "o", "\u001b[?25l\u001b[?7l\u001b[0m\"\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[61.07425, "o", "\u001b[?25l\u001b[?7l\u001b[0mf\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[61.154785, "o", "\u001b[?25l\u001b[?7l\u001b[0mo\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[61.28069, "o", "\u001b[?25l\u001b[?7l\u001b[0mo\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[61.831178, "o", "\u001b[?25l\u001b[?7l\u001b[0m\"\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[61.927243, "o", "\u001b[?25l\u001b[?7l\u001b[0m]\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[62.205321, "o", "\u001b[?25l\u001b[?7l\u001b[C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[62.288705, "o", "\u001b[?25l\u001b[?7l\u001b[0m=\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[62.381831, "o", "\u001b[?25l\u001b[?7l\u001b[C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[62.827726, "o", "\u001b[?25l\u001b[?7l\u001b[0m\"\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[62.999464, "o", "\u001b[?25l\u001b[?7l\u001b[0mb\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[63.070687, "o", "\u001b[?25l\u001b[?7l\u001b[0ma\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[63.157669, "o", "\u001b[?25l\u001b[?7l\u001b[0mr\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[63.421688, "o", "\u001b[?25l\u001b[?7l\u001b[0m\"\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[63.710915, "o", "\u001b[?25l\u001b[?7l\u001b[25D\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[0mbody[\"foo\"] = \"bar\"\u001b[25D\u001b[0m\r\r\n\u001b[J\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[63.711171, "o", "\u001b[?2004l"]
+[63.713816, "o", "\u001b[?1l"]
+[63.71398, "o", "\u001b[6n"]
+[63.717705, "o", "\u001b[?2004h\u001b[?25l\u001b[0m\u001b[?7l\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[6D\u001b[6C\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[63.721978, "o", "\u001b[?25l\u001b[?7l\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[64.750191, "o", "\u001b[?25l\u001b[?7l\u001b[0mc\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[65.540761, "o", "\u001b[?25l\u001b[?7l\u001b[7D\u001b[0m\u001b[J\u001b[0;38;5;28mipdb> \u001b[0mc\u001b[7D\u001b[0m\r\r\n\u001b[J\u001b[?7h\u001b[0m\u001b[?12l\u001b[?25h"]
+[65.541109, "o", "\u001b[?2004l"]
+[65.544155, "o", "\u001b[32mpassed\u001b[0m\r\n"]
+[65.54465, "o", "\r\n"]
+[65.849412, "o", "Name Stmts Miss Branch BrPart Cover\r\n---------------------------------------------------------\r\n"]
+[65.849701, "o", "httpretty/__init__.py 37 2 0 0 95%\r\nhttpretty/compat.py 17 2 0 0 88%\r\nhttpretty/core.py 1007 200 304 59 76%\r\nhttpretty/errors.py 16 2 6 3 77%\r\nhttpretty/http.py 28 0 4 1 97%\r\nhttpretty/utils.py 8 0 4 0 100%\r\nhttpretty/version.py 1 0 0 0 100%\r\n---------------------------------------------------------\r\nTOTAL 1114 206 318 63 77%\r\n"]
+[66.339561, "o", "\u001b[30m-----------------------------------------------------------------------------\u001b[0m\r\n"]
+[66.33975, "o", "1 test run in 49.067 seconds\u001b[32m (1 test passed)\u001b[0m\r\n"]
+[66.340776, "o", "Error in atexit._run_exitfuncs:\r\nTraceback (most recent call last):\r\n"]
+[66.340975, "o", " File \"/Users/gabrielfalcao/projects/personal/HTTPretty/.venv/lib/python3.8/site-packages/IPython/core/history.py\", line 780, in writeout_cache\r\n"]
+[66.342214, "o", " self._writeout_input_cache(conn)\r\n"]
+[66.342401, "o", " File \"/Users/gabrielfalcao/projects/personal/HTTPretty/.venv/lib/python3.8/site-packages/IPython/core/history.py\", line 763, in _writeout_input_cache\r\n"]
+[66.343137, "o", " conn.execute(\"INSERT INTO history VALUES (?, ?, ?, ?)\",\r\nsqlite3.ProgrammingError: SQLite objects created in a thread can only be used in that same thread. The object was created in thread id 123145518436352 and this is thread id 4682546624.\r\n"]
+[66.624442, "o", "HTTPretty $ "]
+[67.88294, "o", "exit\r\n"]
diff --git a/docs/source/conf.py b/docs/source/conf.py
index a50a23f..1b47afb 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -34,6 +34,8 @@ extensions = [
'sphinx.ext.viewcode',
'sphinx.ext.githubpages',
'sphinx.ext.autosummary',
+ 'sphinx.ext.autosummary',
+ 'sphinxcontrib.asciinema',
]
templates_path = ['_templates']
diff --git a/docs/source/guides.rst b/docs/source/guides.rst
new file mode 100644
index 0000000..6349240
--- /dev/null
+++ b/docs/source/guides.rst
@@ -0,0 +1,119 @@
+.. _guides:
+
+
+Guides
+######
+
+A series of guides to using HTTPretty for various interesting
+purposes.
+
+
+.. _matching_urls_via_regular_expressions:
+
+Matching URLs via regular expressions
+=====================================
+
+You can pass a compiled regular expression via :py:func:`re.compile`,
+for example for intercepting all requests to a specific host.
+
+**Example:**
+
+
+.. literalinclude:: _static/regex-example.py
+ :emphasize-lines: 8,10,13
+
+
+Response Callbacks
+==================
+
+
+
+You can use the `body` parameter of
+:py:meth:`~httpretty.core.httpretty.register_uri` in useful, practical
+ways because it accepts a :py:func:`callable` as value.
+
+As matter of example, this is analogous to `defining routes in Flask
+<https://flask.palletsprojects.com/en/2.0.x/quickstart/#routing>`_ when combined with :ref:`matching urls via regular expressions <matching_urls_via_regular_expressions>`
+
+This analogy breaks down, though, because HTTPretty does not provide
+tools to make it easy to handle cookies, parse querystrings etc.
+
+So far this has been a deliberate decision to keep HTTPretty operating
+mostly at the TCP socket level.
+
+Nothing prevents you from being creative with callbacks though, and as
+you will see in the examples below, the request parameter is an
+instance of :py:class:`~httpretty.core.HTTPrettyRequest` which has
+everything you need to create elaborate fake APIs.
+
+
+Defining callbacks
+------------------
+
+The body parameter callback must:
+
+- Accept 3 arguments:
+
+ - `request` - :py:class:`~httpretty.core.HTTPrettyRequest`
+ - `uri` - :py:class:`str`
+ - `headers` - :py:class:`dict` with default response headers (including the ones from the parameters ``adding_headers`` and ``forcing_headers`` of :py:meth:`~httpretty.core.httpretty.register_uri`
+
+- Return 3 a tuple (or list) with 3 values
+
+ - :py:class:`int` - HTTP Status Code
+ - :py:class:`dict` - Response Headers
+ - :py:class:`st` - Response Body
+
+.. important::
+ The **Content-Length** should match the byte length of the body.
+
+ Changing **Content-Length** it in your handler can cause your HTTP
+ client to misbehave, be very intentional when modifying it in our
+ callback.
+
+ The suggested way to manipulate headers is by modifying the
+ response headers passed as argument and returning them in the tuple
+ at the end.
+
+ .. code:: python
+
+ from typing import Tuple
+ from httpretty.core import HTTPrettyRequest
+
+ def my_callback(
+ request: HTTPrettyRequest,
+ url: str,
+ headers: dict
+
+ ) -> Tuple[int, dict, str]:
+
+ headers['Content-Type'] = 'text/plain'
+ return (200, headers, "the body")
+
+ HTTPretty.register_uri(HTTPretty.GET, "https://test.com", body=my_callback)
+
+
+Debug requests interactively with ipdb
+--------------------------------------
+
+The library `ipdb <https://pypi.org/project/ipdb/>`_ comes in handy to
+introspect the request interactively with auto-complete via IPython.
+
+.. literalinclude:: _static/guide-callback-regex-ipdb.py
+ :emphasize-lines: 12,16,17
+
+.. asciinema:: 415981
+ :preload: 1
+
+
+Emulating timeouts
+------------------
+
+In the bug report `#430
+<https://github.com/gabrielfalcao/HTTPretty/issues/430>`_ the contributor `@mariojonke
+<https://github.com/mariojonke>`_ provided a neat example of how to
+emulate read timeout errors by "waiting" inside of a body callback.
+
+
+.. literalinclude:: _static/read-timeout.py
+ :emphasize-lines: 11-13,21,28
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 9591c22..c2a30a6 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -66,6 +66,7 @@ Looking for the `Github Repository <https://github.com/gabrielfalcao/HTTPretty>`
:maxdepth: 2
introduction
+ guides
acks
api
contributing