Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/requests_toolbelt/utils/dump.py @ 0:26e78fe6e8c4 draft
"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
author | shellac |
---|---|
date | Sat, 02 May 2020 07:14:21 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:26e78fe6e8c4 |
---|---|
1 """This module provides functions for dumping information about responses.""" | |
2 import collections | |
3 | |
4 from requests import compat | |
5 | |
6 | |
7 __all__ = ('dump_response', 'dump_all') | |
8 | |
9 HTTP_VERSIONS = { | |
10 9: b'0.9', | |
11 10: b'1.0', | |
12 11: b'1.1', | |
13 } | |
14 | |
15 _PrefixSettings = collections.namedtuple('PrefixSettings', | |
16 ['request', 'response']) | |
17 | |
18 | |
19 class PrefixSettings(_PrefixSettings): | |
20 def __new__(cls, request, response): | |
21 request = _coerce_to_bytes(request) | |
22 response = _coerce_to_bytes(response) | |
23 return super(PrefixSettings, cls).__new__(cls, request, response) | |
24 | |
25 | |
26 def _get_proxy_information(response): | |
27 if getattr(response.connection, 'proxy_manager', False): | |
28 proxy_info = {} | |
29 request_url = response.request.url | |
30 if request_url.startswith('https://'): | |
31 proxy_info['method'] = 'CONNECT' | |
32 | |
33 proxy_info['request_path'] = request_url | |
34 return proxy_info | |
35 return None | |
36 | |
37 | |
38 def _format_header(name, value): | |
39 return (_coerce_to_bytes(name) + b': ' + _coerce_to_bytes(value) + | |
40 b'\r\n') | |
41 | |
42 | |
43 def _build_request_path(url, proxy_info): | |
44 uri = compat.urlparse(url) | |
45 proxy_url = proxy_info.get('request_path') | |
46 if proxy_url is not None: | |
47 request_path = _coerce_to_bytes(proxy_url) | |
48 return request_path, uri | |
49 | |
50 request_path = _coerce_to_bytes(uri.path) | |
51 if uri.query: | |
52 request_path += b'?' + _coerce_to_bytes(uri.query) | |
53 | |
54 return request_path, uri | |
55 | |
56 | |
57 def _dump_request_data(request, prefixes, bytearr, proxy_info=None): | |
58 if proxy_info is None: | |
59 proxy_info = {} | |
60 | |
61 prefix = prefixes.request | |
62 method = _coerce_to_bytes(proxy_info.pop('method', request.method)) | |
63 request_path, uri = _build_request_path(request.url, proxy_info) | |
64 | |
65 # <prefix><METHOD> <request-path> HTTP/1.1 | |
66 bytearr.extend(prefix + method + b' ' + request_path + b' HTTP/1.1\r\n') | |
67 | |
68 # <prefix>Host: <request-host> OR host header specified by user | |
69 headers = request.headers.copy() | |
70 host_header = _coerce_to_bytes(headers.pop('Host', uri.netloc)) | |
71 bytearr.extend(prefix + b'Host: ' + host_header + b'\r\n') | |
72 | |
73 for name, value in headers.items(): | |
74 bytearr.extend(prefix + _format_header(name, value)) | |
75 | |
76 bytearr.extend(prefix + b'\r\n') | |
77 if request.body: | |
78 if isinstance(request.body, compat.basestring): | |
79 bytearr.extend(prefix + _coerce_to_bytes(request.body)) | |
80 else: | |
81 # In the event that the body is a file-like object, let's not try | |
82 # to read everything into memory. | |
83 bytearr.extend(b'<< Request body is not a string-like type >>') | |
84 bytearr.extend(b'\r\n') | |
85 | |
86 | |
87 def _dump_response_data(response, prefixes, bytearr): | |
88 prefix = prefixes.response | |
89 # Let's interact almost entirely with urllib3's response | |
90 raw = response.raw | |
91 | |
92 # Let's convert the version int from httplib to bytes | |
93 version_str = HTTP_VERSIONS.get(raw.version, b'?') | |
94 | |
95 # <prefix>HTTP/<version_str> <status_code> <reason> | |
96 bytearr.extend(prefix + b'HTTP/' + version_str + b' ' + | |
97 str(raw.status).encode('ascii') + b' ' + | |
98 _coerce_to_bytes(response.reason) + b'\r\n') | |
99 | |
100 headers = raw.headers | |
101 for name in headers.keys(): | |
102 for value in headers.getlist(name): | |
103 bytearr.extend(prefix + _format_header(name, value)) | |
104 | |
105 bytearr.extend(prefix + b'\r\n') | |
106 | |
107 bytearr.extend(response.content) | |
108 | |
109 | |
110 def _coerce_to_bytes(data): | |
111 if not isinstance(data, bytes) and hasattr(data, 'encode'): | |
112 data = data.encode('utf-8') | |
113 # Don't bail out with an exception if data is None | |
114 return data if data is not None else b'' | |
115 | |
116 | |
117 def dump_response(response, request_prefix=b'< ', response_prefix=b'> ', | |
118 data_array=None): | |
119 """Dump a single request-response cycle's information. | |
120 | |
121 This will take a response object and dump only the data that requests can | |
122 see for that single request-response cycle. | |
123 | |
124 Example:: | |
125 | |
126 import requests | |
127 from requests_toolbelt.utils import dump | |
128 | |
129 resp = requests.get('https://api.github.com/users/sigmavirus24') | |
130 data = dump.dump_response(resp) | |
131 print(data.decode('utf-8')) | |
132 | |
133 :param response: | |
134 The response to format | |
135 :type response: :class:`requests.Response` | |
136 :param request_prefix: (*optional*) | |
137 Bytes to prefix each line of the request data | |
138 :type request_prefix: :class:`bytes` | |
139 :param response_prefix: (*optional*) | |
140 Bytes to prefix each line of the response data | |
141 :type response_prefix: :class:`bytes` | |
142 :param data_array: (*optional*) | |
143 Bytearray to which we append the request-response cycle data | |
144 :type data_array: :class:`bytearray` | |
145 :returns: Formatted bytes of request and response information. | |
146 :rtype: :class:`bytearray` | |
147 """ | |
148 data = data_array if data_array is not None else bytearray() | |
149 prefixes = PrefixSettings(request_prefix, response_prefix) | |
150 | |
151 if not hasattr(response, 'request'): | |
152 raise ValueError('Response has no associated request') | |
153 | |
154 proxy_info = _get_proxy_information(response) | |
155 _dump_request_data(response.request, prefixes, data, | |
156 proxy_info=proxy_info) | |
157 _dump_response_data(response, prefixes, data) | |
158 return data | |
159 | |
160 | |
161 def dump_all(response, request_prefix=b'< ', response_prefix=b'> '): | |
162 """Dump all requests and responses including redirects. | |
163 | |
164 This takes the response returned by requests and will dump all | |
165 request-response pairs in the redirect history in order followed by the | |
166 final request-response. | |
167 | |
168 Example:: | |
169 | |
170 import requests | |
171 from requests_toolbelt.utils import dump | |
172 | |
173 resp = requests.get('https://httpbin.org/redirect/5') | |
174 data = dump.dump_all(resp) | |
175 print(data.decode('utf-8')) | |
176 | |
177 :param response: | |
178 The response to format | |
179 :type response: :class:`requests.Response` | |
180 :param request_prefix: (*optional*) | |
181 Bytes to prefix each line of the request data | |
182 :type request_prefix: :class:`bytes` | |
183 :param response_prefix: (*optional*) | |
184 Bytes to prefix each line of the response data | |
185 :type response_prefix: :class:`bytes` | |
186 :returns: Formatted bytes of request and response information. | |
187 :rtype: :class:`bytearray` | |
188 """ | |
189 data = bytearray() | |
190 | |
191 history = list(response.history[:]) | |
192 history.append(response) | |
193 | |
194 for response in history: | |
195 dump_response(response, request_prefix, response_prefix, data) | |
196 | |
197 return data |