diff options
author | Shubham Saini <shubham6405@gmail.com> | 2018-12-11 10:01:23 +0000 |
---|---|---|
committer | Shubham Saini <shubham6405@gmail.com> | 2018-12-11 10:01:23 +0000 |
commit | 68df54d6629ec019142eb149dd037774f2d11e7c (patch) | |
tree | 345bc22d46b4e01a4ba8303b94278952a4ed2b9e /venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/requests/models.py |
First commit
Diffstat (limited to 'venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/requests/models.py')
-rw-r--r-- | venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/requests/models.py | 948 |
1 files changed, 948 insertions, 0 deletions
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/requests/models.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/requests/models.py new file mode 100644 index 0000000..6f5b0fb --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/requests/models.py | |||
@@ -0,0 +1,948 @@ | |||
1 | # -*- coding: utf-8 -*- | ||
2 | |||
3 | """ | ||
4 | requests.models | ||
5 | ~~~~~~~~~~~~~~~ | ||
6 | |||
7 | This module contains the primary objects that power Requests. | ||
8 | """ | ||
9 | |||
10 | import collections | ||
11 | import datetime | ||
12 | import sys | ||
13 | |||
14 | # Import encoding now, to avoid implicit import later. | ||
15 | # Implicit import within threads may cause LookupError when standard library is in a ZIP, | ||
16 | # such as in Embedded Python. See https://github.com/requests/requests/issues/3578. | ||
17 | import encodings.idna | ||
18 | |||
19 | from pip._vendor.urllib3.fields import RequestField | ||
20 | from pip._vendor.urllib3.filepost import encode_multipart_formdata | ||
21 | from pip._vendor.urllib3.util import parse_url | ||
22 | from pip._vendor.urllib3.exceptions import ( | ||
23 | DecodeError, ReadTimeoutError, ProtocolError, LocationParseError) | ||
24 | |||
25 | from io import UnsupportedOperation | ||
26 | from .hooks import default_hooks | ||
27 | from .structures import CaseInsensitiveDict | ||
28 | |||
29 | from .auth import HTTPBasicAuth | ||
30 | from .cookies import cookiejar_from_dict, get_cookie_header, _copy_cookie_jar | ||
31 | from .exceptions import ( | ||
32 | HTTPError, MissingSchema, InvalidURL, ChunkedEncodingError, | ||
33 | ContentDecodingError, ConnectionError, StreamConsumedError) | ||
34 | from ._internal_utils import to_native_string, unicode_is_ascii | ||
35 | from .utils import ( | ||
36 | guess_filename, get_auth_from_url, requote_uri, | ||
37 | stream_decode_response_unicode, to_key_val_list, parse_header_links, | ||
38 | iter_slices, guess_json_utf, super_len, check_header_validity) | ||
39 | from .compat import ( | ||
40 | cookielib, urlunparse, urlsplit, urlencode, str, bytes, | ||
41 | is_py2, chardet, builtin_str, basestring) | ||
42 | from .compat import json as complexjson | ||
43 | from .status_codes import codes | ||
44 | |||
45 | #: The set of HTTP status codes that indicate an automatically | ||
46 | #: processable redirect. | ||
47 | REDIRECT_STATI = ( | ||
48 | codes.moved, # 301 | ||
49 | codes.found, # 302 | ||
50 | codes.other, # 303 | ||
51 | codes.temporary_redirect, # 307 | ||
52 | codes.permanent_redirect, # 308 | ||
53 | ) | ||
54 | |||
55 | DEFAULT_REDIRECT_LIMIT = 30 | ||
56 | CONTENT_CHUNK_SIZE = 10 * 1024 | ||
57 | ITER_CHUNK_SIZE = 512 | ||
58 | |||
59 | |||
60 | class RequestEncodingMixin(object): | ||
61 | @property | ||
62 | def path_url(self): | ||
63 | """Build the path URL to use.""" | ||
64 | |||
65 | url = [] | ||
66 | |||
67 | p = urlsplit(self.url) | ||
68 | |||
69 | path = p.path | ||
70 | if not path: | ||
71 | path = '/' | ||
72 | |||
73 | url.append(path) | ||
74 | |||
75 | query = p.query | ||
76 | if query: | ||
77 | url.append('?') | ||
78 | url.append(query) | ||
79 | |||
80 | return ''.join(url) | ||
81 | |||
82 | @staticmethod | ||
83 | def _encode_params(data): | ||
84 | """Encode parameters in a piece of data. | ||
85 | |||
86 | Will successfully encode parameters when passed as a dict or a list of | ||
87 | 2-tuples. Order is retained if data is a list of 2-tuples but arbitrary | ||
88 | if parameters are supplied as a dict. | ||
89 | """ | ||
90 | |||
91 | if isinstance(data, (str, bytes)): | ||
92 | return data | ||
93 | elif hasattr(data, 'read'): | ||
94 | return data | ||
95 | elif hasattr(data, '__iter__'): | ||
96 | result = [] | ||
97 | for k, vs in to_key_val_list(data): | ||
98 | if isinstance(vs, basestring) or not hasattr(vs, '__iter__'): | ||
99 | vs = [vs] | ||
100 | for v in vs: | ||
101 | if v is not None: | ||
102 | result.append( | ||
103 | (k.encode('utf-8') if isinstance(k, str) else k, | ||
104 | v.encode('utf-8') if isinstance(v, str) else v)) | ||
105 | return urlencode(result, doseq=True) | ||
106 | else: | ||
107 | return data | ||
108 | |||
109 | @staticmethod | ||
110 | def _encode_files(files, data): | ||
111 | """Build the body for a multipart/form-data request. | ||
112 | |||
113 | Will successfully encode files when passed as a dict or a list of | ||
114 | tuples. Order is retained if data is a list of tuples but arbitrary | ||
115 | if parameters are supplied as a dict. | ||
116 | The tuples may be 2-tuples (filename, fileobj), 3-tuples (filename, fileobj, contentype) | ||
117 | or 4-tuples (filename, fileobj, contentype, custom_headers). | ||
118 | """ | ||
119 | if (not files): | ||
120 | raise ValueError("Files must be provided.") | ||
121 | elif isinstance(data, basestring): | ||
122 | raise ValueError("Data must not be a string.") | ||
123 | |||
124 | new_fields = [] | ||
125 | fields = to_key_val_list(data or {}) | ||
126 | files = to_key_val_list(files or {}) | ||
127 | |||
128 | for field, val in fields: | ||
129 | if isinstance(val, basestring) or not hasattr(val, '__iter__'): | ||
130 | val = [val] | ||
131 | for v in val: | ||
132 | if v is not None: | ||
133 | # Don't call str() on bytestrings: in Py3 it all goes wrong. | ||
134 | if not isinstance(v, bytes): | ||
135 | v = str(v) | ||
136 | |||
137 | new_fields.append( | ||
138 | (field.decode('utf-8') if isinstance(field, bytes) else field, | ||
139 | v.encode('utf-8') if isinstance(v, str) else v)) | ||
140 | |||
141 | for (k, v) in files: | ||
142 | # support for explicit filename | ||
143 | ft = None | ||
144 | fh = None | ||
145 | if isinstance(v, (tuple, list)): | ||
146 | if len(v) == 2: | ||
147 | fn, fp = v | ||
148 | elif len(v) == 3: | ||
149 | fn, fp, ft = v | ||
150 | else: | ||
151 | fn, fp, ft, fh = v | ||
152 | else: | ||
153 | fn = guess_filename(v) or k | ||
154 | fp = v | ||
155 | |||
156 | if isinstance(fp, (str, bytes, bytearray)): | ||
157 | fdata = fp | ||
158 | else: | ||
159 | fdata = fp.read() | ||
160 | |||
161 | rf = RequestField(name=k, data=fdata, filename=fn, headers=fh) | ||
162 | rf.make_multipart(content_type=ft) | ||
163 | new_fields.append(rf) | ||
164 | |||
165 | body, content_type = encode_multipart_formdata(new_fields) | ||
166 | |||
167 | return body, content_type | ||
168 | |||
169 | |||
170 | class RequestHooksMixin(object): | ||
171 | def register_hook(self, event, hook): | ||
172 | """Properly register a hook.""" | ||
173 | |||
174 | if event not in self.hooks: | ||
175 | raise ValueError('Unsupported event specified, with event name "%s"' % (event)) | ||
176 | |||
177 | if isinstance(hook, collections.Callable): | ||
178 | self.hooks[event].append(hook) | ||
179 | elif hasattr(hook, '__iter__'): | ||
180 | self.hooks[event].extend(h for h in hook if isinstance(h, collections.Callable)) | ||
181 | |||
182 | def deregister_hook(self, event, hook): | ||
183 | """Deregister a previously registered hook. | ||
184 | Returns True if the hook existed, False if not. | ||
185 | """ | ||
186 | |||
187 | try: | ||
188 | self.hooks[event].remove(hook) | ||
189 | return True | ||
190 | except ValueError: | ||
191 | return False | ||
192 | |||
193 | |||
194 | class Request(RequestHooksMixin): | ||
195 | """A user-created :class:`Request <Request>` object. | ||
196 | |||
197 | Used to prepare a :class:`PreparedRequest <PreparedRequest>`, which is sent to the server. | ||
198 | |||
199 | :param method: HTTP method to use. | ||
200 | :param url: URL to send. | ||
201 | :param headers: dictionary of headers to send. | ||
202 | :param files: dictionary of {filename: fileobject} files to multipart upload. | ||
203 | :param data: the body to attach to the request. If a dictionary is provided, form-encoding will take place. | ||
204 | :param json: json for the body to attach to the request (if files or data is not specified). | ||
205 | :param params: dictionary of URL parameters to append to the URL. | ||
206 | :param auth: Auth handler or (user, pass) tuple. | ||
207 | :param cookies: dictionary or CookieJar of cookies to attach to this request. | ||
208 | :param hooks: dictionary of callback hooks, for internal usage. | ||
209 | |||
210 | Usage:: | ||
211 | |||
212 | >>> import requests | ||
213 | >>> req = requests.Request('GET', 'http://httpbin.org/get') | ||
214 | >>> req.prepare() | ||
215 | <PreparedRequest [GET]> | ||
216 | """ | ||
217 | |||
218 | def __init__(self, | ||
219 | method=None, url=None, headers=None, files=None, data=None, | ||
220 | params=None, auth=None, cookies=None, hooks=None, json=None): | ||
221 | |||
222 | # Default empty dicts for dict params. | ||
223 | data = [] if data is None else data | ||
224 | files = [] if files is None else files | ||
225 | headers = {} if headers is None else headers | ||
226 | params = {} if params is None else params | ||
227 | hooks = {} if hooks is None else hooks | ||
228 | |||
229 | self.hooks = default_hooks() | ||
230 | for (k, v) in list(hooks.items()): | ||
231 | self.register_hook(event=k, hook=v) | ||
232 | |||
233 | self.method = method | ||
234 | self.url = url | ||
235 | self.headers = headers | ||
236 | self.files = files | ||
237 | self.data = data | ||
238 | self.json = json | ||
239 | self.params = params | ||
240 | self.auth = auth | ||
241 | self.cookies = cookies | ||
242 | |||
243 | def __repr__(self): | ||
244 | return '<Request [%s]>' % (self.method) | ||
245 | |||
246 | def prepare(self): | ||
247 | """Constructs a :class:`PreparedRequest <PreparedRequest>` for transmission and returns it.""" | ||
248 | p = PreparedRequest() | ||
249 | p.prepare( | ||
250 | method=self.method, | ||
251 | url=self.url, | ||
252 | headers=self.headers, | ||
253 | files=self.files, | ||
254 | data=self.data, | ||
255 | json=self.json, | ||
256 | params=self.params, | ||
257 | auth=self.auth, | ||
258 | cookies=self.cookies, | ||
259 | hooks=self.hooks, | ||
260 | ) | ||
261 | return p | ||
262 | |||
263 | |||
264 | class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): | ||
265 | """The fully mutable :class:`PreparedRequest <PreparedRequest>` object, | ||
266 | containing the exact bytes that will be sent to the server. | ||
267 | |||
268 | Generated from either a :class:`Request <Request>` object or manually. | ||
269 | |||
270 | Usage:: | ||
271 | |||
272 | >>> import requests | ||
273 | >>> req = requests.Request('GET', 'http://httpbin.org/get') | ||
274 | >>> r = req.prepare() | ||
275 | <PreparedRequest [GET]> | ||
276 | |||
277 | >>> s = requests.Session() | ||
278 | >>> s.send(r) | ||
279 | <Response [200]> | ||
280 | """ | ||
281 | |||
282 | def __init__(self): | ||
283 | #: HTTP verb to send to the server. | ||
284 | self.method = None | ||
285 | #: HTTP URL to send the request to. | ||
286 | self.url = None | ||
287 | #: dictionary of HTTP headers. | ||
288 | self.headers = None | ||
289 | # The `CookieJar` used to create the Cookie header will be stored here | ||
290 | # after prepare_cookies is called | ||
291 | self._cookies = None | ||
292 | #: request body to send to the server. | ||
293 | self.body = None | ||
294 | #: dictionary of callback hooks, for internal usage. | ||
295 | self.hooks = default_hooks() | ||
296 | #: integer denoting starting position of a readable file-like body. | ||
297 | self._body_position = None | ||
298 | |||
299 | def prepare(self, | ||
300 | method=None, url=None, headers=None, files=None, data=None, | ||
301 | params=None, auth=None, cookies=None, hooks=None, json=None): | ||
302 | """Prepares the entire request with the given parameters.""" | ||
303 | |||
304 | self.prepare_method(method) | ||
305 | self.prepare_url(url, params) | ||
306 | self.prepare_headers(headers) | ||
307 | self.prepare_cookies(cookies) | ||
308 | self.prepare_body(data, files, json) | ||
309 | self.prepare_auth(auth, url) | ||
310 | |||
311 | # Note that prepare_auth must be last to enable authentication schemes | ||
312 | # such as OAuth to work on a fully prepared request. | ||
313 | |||
314 | # This MUST go after prepare_auth. Authenticators could add a hook | ||
315 | self.prepare_hooks(hooks) | ||
316 | |||
317 | def __repr__(self): | ||
318 | return '<PreparedRequest [%s]>' % (self.method) | ||
319 | |||
320 | def copy(self): | ||
321 | p = PreparedRequest() | ||
322 | p.method = self.method | ||
323 | p.url = self.url | ||
324 | p.headers = self.headers.copy() if self.headers is not None else None | ||
325 | p._cookies = _copy_cookie_jar(self._cookies) | ||
326 | p.body = self.body | ||
327 | p.hooks = self.hooks | ||
328 | p._body_position = self._body_position | ||
329 | return p | ||
330 | |||
331 | def prepare_method(self, method): | ||
332 | """Prepares the given HTTP method.""" | ||
333 | self.method = method | ||
334 | if self.method is not None: | ||
335 | self.method = to_native_string(self.method.upper()) | ||
336 | |||
337 | @staticmethod | ||
338 | def _get_idna_encoded_host(host): | ||
339 | from pip._vendor import idna | ||
340 | |||
341 | try: | ||
342 | host = idna.encode(host, uts46=True).decode('utf-8') | ||
343 | except idna.IDNAError: | ||
344 | raise UnicodeError | ||
345 | return host | ||
346 | |||
347 | def prepare_url(self, url, params): | ||
348 | """Prepares the given HTTP URL.""" | ||
349 | #: Accept objects that have string representations. | ||
350 | #: We're unable to blindly call unicode/str functions | ||
351 | #: as this will include the bytestring indicator (b'') | ||
352 | #: on python 3.x. | ||
353 | #: https://github.com/requests/requests/pull/2238 | ||
354 | if isinstance(url, bytes): | ||
355 | url = url.decode('utf8') | ||
356 | else: | ||
357 | url = unicode(url) if is_py2 else str(url) | ||
358 | |||
359 | # Remove leading whitespaces from url | ||
360 | url = url.lstrip() | ||
361 | |||
362 | # Don't do any URL preparation for non-HTTP schemes like `mailto`, | ||
363 | # `data` etc to work around exceptions from `url_parse`, which | ||
364 | # handles RFC 3986 only. | ||
365 | if ':' in url and not url.lower().startswith('http'): | ||
366 | self.url = url | ||
367 | return | ||
368 | |||
369 | # Support for unicode domain names and paths. | ||
370 | try: | ||
371 | scheme, auth, host, port, path, query, fragment = parse_url(url) | ||
372 | except LocationParseError as e: | ||
373 | raise InvalidURL(*e.args) | ||
374 | |||
375 | if not scheme: | ||
376 | error = ("Invalid URL {0!r}: No schema supplied. Perhaps you meant http://{0}?") | ||
377 | error = error.format(to_native_string(url, 'utf8')) | ||
378 | |||
379 | raise MissingSchema(error) | ||
380 | |||
381 | if not host: | ||
382 | raise InvalidURL("Invalid URL %r: No host supplied" % url) | ||
383 | |||
384 | # In general, we want to try IDNA encoding the hostname if the string contains | ||
385 | # non-ASCII characters. This allows users to automatically get the correct IDNA | ||
386 | # behaviour. For strings containing only ASCII characters, we need to also verify | ||
387 | # it doesn't start with a wildcard (*), before allowing the unencoded hostname. | ||
388 | if not unicode_is_ascii(host): | ||
389 | try: | ||
390 | host = self._get_idna_encoded_host(host) | ||
391 | except UnicodeError: | ||
392 | raise InvalidURL('URL has an invalid label.') | ||
393 | elif host.startswith(u'*'): | ||
394 | raise InvalidURL('URL has an invalid label.') | ||
395 | |||
396 | # Carefully reconstruct the network location | ||
397 | netloc = auth or '' | ||
398 | if netloc: | ||
399 | netloc += '@' | ||
400 | netloc += host | ||
401 | if port: | ||
402 | netloc += ':' + str(port) | ||
403 | |||
404 | # Bare domains aren't valid URLs. | ||
405 | if not path: | ||
406 | path = '/' | ||
407 | |||
408 | if is_py2: | ||
409 | if isinstance(scheme, str): | ||
410 | scheme = scheme.encode('utf-8') | ||
411 | if isinstance(netloc, str): | ||
412 | netloc = netloc.encode('utf-8') | ||
413 | if isinstance(path, str): | ||
414 | path = path.encode('utf-8') | ||
415 | if isinstance(query, str): | ||
416 | query = query.encode('utf-8') | ||
417 | if isinstance(fragment, str): | ||
418 | fragment = fragment.encode('utf-8') | ||
419 | |||
420 | if isinstance(params, (str, bytes)): | ||
421 | params = to_native_string(params) | ||
422 | |||
423 | enc_params = self._encode_params(params) | ||
424 | if enc_params: | ||
425 | if query: | ||
426 | query = '%s&%s' % (query, enc_params) | ||
427 | else: | ||
428 | query = enc_params | ||
429 | |||
430 | url = requote_uri(urlunparse([scheme, netloc, path, None, query, fragment])) | ||
431 | self.url = url | ||
432 | |||
433 | def prepare_headers(self, headers): | ||
434 | """Prepares the given HTTP headers.""" | ||
435 | |||
436 | self.headers = CaseInsensitiveDict() | ||
437 | if headers: | ||
438 | for header in headers.items(): | ||
439 | # Raise exception on invalid header value. | ||
440 | check_header_validity(header) | ||
441 | name, value = header | ||
442 | self.headers[to_native_string(name)] = value | ||
443 | |||
444 | def prepare_body(self, data, files, json=None): | ||
445 | """Prepares the given HTTP body data.""" | ||
446 | |||
447 | # Check if file, fo, generator, iterator. | ||
448 | # If not, run through normal process. | ||
449 | |||
450 | # Nottin' on you. | ||
451 | body = None | ||
452 | content_type = None | ||
453 | |||
454 | if not data and json is not None: | ||
455 | # urllib3 requires a bytes-like body. Python 2's json.dumps | ||
456 | # provides this natively, but Python 3 gives a Unicode string. | ||
457 | content_type = 'application/json' | ||
458 | body = complexjson.dumps(json) | ||
459 | if not isinstance(body, bytes): | ||
460 | body = body.encode('utf-8') | ||
461 | |||
462 | is_stream = all([ | ||
463 | hasattr(data, '__iter__'), | ||
464 | not isinstance(data, (basestring, list, tuple, collections.Mapping)) | ||
465 | ]) | ||
466 | |||
467 | try: | ||
468 | length = super_len(data) | ||
469 | except (TypeError, AttributeError, UnsupportedOperation): | ||
470 | length = None | ||
471 | |||
472 | if is_stream: | ||
473 | body = data | ||
474 | |||
475 | if getattr(body, 'tell', None) is not None: | ||
476 | # Record the current file position before reading. | ||
477 | # This will allow us to rewind a file in the event | ||
478 | # of a redirect. | ||
479 | try: | ||
480 | self._body_position = body.tell() | ||
481 | except (IOError, OSError): | ||
482 | # This differentiates from None, allowing us to catch | ||
483 | # a failed `tell()` later when trying to rewind the body | ||
484 | self._body_position = object() | ||
485 | |||
486 | if files: | ||
487 | raise NotImplementedError('Streamed bodies and files are mutually exclusive.') | ||
488 | |||
489 | if length: | ||
490 | self.headers['Content-Length'] = builtin_str(length) | ||
491 | else: | ||
492 | self.headers['Transfer-Encoding'] = 'chunked' | ||
493 | else: | ||
494 | # Multi-part file uploads. | ||
495 | if files: | ||
496 | (body, content_type) = self._encode_files(files, data) | ||
497 | else: | ||
498 | if data: | ||
499 | body = self._encode_params(data) | ||
500 | if isinstance(data, basestring) or hasattr(data, 'read'): | ||
501 | content_type = None | ||
502 | else: | ||
503 | content_type = 'application/x-www-form-urlencoded' | ||
504 | |||
505 | self.prepare_content_length(body) | ||
506 | |||
507 | # Add content-type if it wasn't explicitly provided. | ||
508 | if content_type and ('content-type' not in self.headers): | ||
509 | self.headers['Content-Type'] = content_type | ||
510 | |||
511 | self.body = body | ||
512 | |||
513 | def prepare_content_length(self, body): | ||
514 | """Prepare Content-Length header based on request method and body""" | ||
515 | if body is not None: | ||
516 | length = super_len(body) | ||
517 | if length: | ||
518 | # If length exists, set it. Otherwise, we fallback | ||
519 | # to Transfer-Encoding: chunked. | ||
520 | self.headers['Content-Length'] = builtin_str(length) | ||
521 | elif self.method not in ('GET', 'HEAD') and self.headers.get('Content-Length') is None: | ||
522 | # Set Content-Length to 0 for methods that can have a body | ||
523 | # but don't provide one. (i.e. not GET or HEAD) | ||
524 | self.headers['Content-Length'] = '0' | ||
525 | |||
526 | def prepare_auth(self, auth, url=''): | ||
527 | """Prepares the given HTTP auth data.""" | ||
528 | |||
529 | # If no Auth is explicitly provided, extract it from the URL first. | ||
530 | if auth is None: | ||
531 | url_auth = get_auth_from_url(self.url) | ||
532 | auth = url_auth if any(url_auth) else None | ||
533 | |||
534 | if auth: | ||
535 | if isinstance(auth, tuple) and len(auth) == 2: | ||
536 | # special-case basic HTTP auth | ||
537 | auth = HTTPBasicAuth(*auth) | ||
538 | |||
539 | # Allow auth to make its changes. | ||
540 | r = auth(self) | ||
541 | |||
542 | # Update self to reflect the auth changes. | ||
543 | self.__dict__.update(r.__dict__) | ||
544 | |||
545 | # Recompute Content-Length | ||
546 | self.prepare_content_length(self.body) | ||
547 | |||
548 | def prepare_cookies(self, cookies): | ||
549 | """Prepares the given HTTP cookie data. | ||
550 | |||
551 | This function eventually generates a ``Cookie`` header from the | ||
552 | given cookies using cookielib. Due to cookielib's design, the header | ||
553 | will not be regenerated if it already exists, meaning this function | ||
554 | can only be called once for the life of the | ||
555 | :class:`PreparedRequest <PreparedRequest>` object. Any subsequent calls | ||
556 | to ``prepare_cookies`` will have no actual effect, unless the "Cookie" | ||
557 | header is removed beforehand. | ||
558 | """ | ||
559 | if isinstance(cookies, cookielib.CookieJar): | ||
560 | self._cookies = cookies | ||
561 | else: | ||
562 | self._cookies = cookiejar_from_dict(cookies) | ||
563 | |||
564 | cookie_header = get_cookie_header(self._cookies, self) | ||
565 | if cookie_header is not None: | ||
566 | self.headers['Cookie'] = cookie_header | ||
567 | |||
568 | def prepare_hooks(self, hooks): | ||
569 | """Prepares the given hooks.""" | ||
570 | # hooks can be passed as None to the prepare method and to this | ||
571 | # method. To prevent iterating over None, simply use an empty list | ||
572 | # if hooks is False-y | ||
573 | hooks = hooks or [] | ||
574 | for event in hooks: | ||
575 | self.register_hook(event, hooks[event]) | ||
576 | |||
577 | |||
578 | class Response(object): | ||
579 | """The :class:`Response <Response>` object, which contains a | ||
580 | server's response to an HTTP request. | ||
581 | """ | ||
582 | |||
583 | __attrs__ = [ | ||
584 | '_content', 'status_code', 'headers', 'url', 'history', | ||
585 | 'encoding', 'reason', 'cookies', 'elapsed', 'request' | ||
586 | ] | ||
587 | |||
588 | def __init__(self): | ||
589 | self._content = False | ||
590 | self._content_consumed = False | ||
591 | self._next = None | ||
592 | |||
593 | #: Integer Code of responded HTTP Status, e.g. 404 or 200. | ||
594 | self.status_code = None | ||
595 | |||
596 | #: Case-insensitive Dictionary of Response Headers. | ||
597 | #: For example, ``headers['content-encoding']`` will return the | ||
598 | #: value of a ``'Content-Encoding'`` response header. | ||
599 | self.headers = CaseInsensitiveDict() | ||
600 | |||
601 | #: File-like object representation of response (for advanced usage). | ||
602 | #: Use of ``raw`` requires that ``stream=True`` be set on the request. | ||
603 | # This requirement does not apply for use internally to Requests. | ||
604 | self.raw = None | ||
605 | |||
606 | #: Final URL location of Response. | ||
607 | self.url = None | ||
608 | |||
609 | #: Encoding to decode with when accessing r.text. | ||
610 | self.encoding = None | ||
611 | |||
612 | #: A list of :class:`Response <Response>` objects from | ||
613 | #: the history of the Request. Any redirect responses will end | ||
614 | #: up here. The list is sorted from the oldest to the most recent request. | ||
615 | self.history = [] | ||
616 | |||
617 | #: Textual reason of responded HTTP Status, e.g. "Not Found" or "OK". | ||
618 | self.reason = None | ||
619 | |||
620 | #: A CookieJar of Cookies the server sent back. | ||
621 | self.cookies = cookiejar_from_dict({}) | ||
622 | |||
623 | #: The amount of time elapsed between sending the request | ||
624 | #: and the arrival of the response (as a timedelta). | ||
625 | #: This property specifically measures the time taken between sending | ||
626 | #: the first byte of the request and finishing parsing the headers. It | ||
627 | #: is therefore unaffected by consuming the response content or the | ||
628 | #: value of the ``stream`` keyword argument. | ||
629 | self.elapsed = datetime.timedelta(0) | ||
630 | |||
631 | #: The :class:`PreparedRequest <PreparedRequest>` object to which this | ||
632 | #: is a response. | ||
633 | self.request = None | ||
634 | |||
635 | def __enter__(self): | ||
636 | return self | ||
637 | |||
638 | def __exit__(self, *args): | ||
639 | self.close() | ||
640 | |||
641 | def __getstate__(self): | ||
642 | # Consume everything; accessing the content attribute makes | ||
643 | # sure the content has been fully read. | ||
644 | if not self._content_consumed: | ||
645 | self.content | ||
646 | |||
647 | return dict( | ||
648 | (attr, getattr(self, attr, None)) | ||
649 | for attr in self.__attrs__ | ||
650 | ) | ||
651 | |||
652 | def __setstate__(self, state): | ||
653 | for name, value in state.items(): | ||
654 | setattr(self, name, value) | ||
655 | |||
656 | # pickled objects do not have .raw | ||
657 | setattr(self, '_content_consumed', True) | ||
658 | setattr(self, 'raw', None) | ||
659 | |||
660 | def __repr__(self): | ||
661 | return '<Response [%s]>' % (self.status_code) | ||
662 | |||
663 | def __bool__(self): | ||
664 | """Returns True if :attr:`status_code` is less than 400. | ||
665 | |||
666 | This attribute checks if the status code of the response is between | ||
667 | 400 and 600 to see if there was a client error or a server error. If | ||
668 | the status code, is between 200 and 400, this will return True. This | ||
669 | is **not** a check to see if the response code is ``200 OK``. | ||
670 | """ | ||
671 | return self.ok | ||
672 | |||
673 | def __nonzero__(self): | ||
674 | """Returns True if :attr:`status_code` is less than 400. | ||
675 | |||
676 | This attribute checks if the status code of the response is between | ||
677 | 400 and 600 to see if there was a client error or a server error. If | ||
678 | the status code, is between 200 and 400, this will return True. This | ||
679 | is **not** a check to see if the response code is ``200 OK``. | ||
680 | """ | ||
681 | return self.ok | ||
682 | |||
683 | def __iter__(self): | ||
684 | """Allows you to use a response as an iterator.""" | ||
685 | return self.iter_content(128) | ||
686 | |||
687 | @property | ||
688 | def ok(self): | ||
689 | """Returns True if :attr:`status_code` is less than 400. | ||
690 | |||
691 | This attribute checks if the status code of the response is between | ||
692 | 400 and 600 to see if there was a client error or a server error. If | ||
693 | the status code, is between 200 and 400, this will return True. This | ||
694 | is **not** a check to see if the response code is ``200 OK``. | ||
695 | """ | ||
696 | try: | ||
697 | self.raise_for_status() | ||
698 | except HTTPError: | ||
699 | return False | ||
700 | return True | ||
701 | |||
702 | @property | ||
703 | def is_redirect(self): | ||
704 | """True if this Response is a well-formed HTTP redirect that could have | ||
705 | been processed automatically (by :meth:`Session.resolve_redirects`). | ||
706 | """ | ||
707 | return ('location' in self.headers and self.status_code in REDIRECT_STATI) | ||
708 | |||
709 | @property | ||
710 | def is_permanent_redirect(self): | ||
711 | """True if this Response one of the permanent versions of redirect.""" | ||
712 | return ('location' in self.headers and self.status_code in (codes.moved_permanently, codes.permanent_redirect)) | ||
713 | |||
714 | @property | ||
715 | def next(self): | ||
716 | """Returns a PreparedRequest for the next request in a redirect chain, if there is one.""" | ||
717 | return self._next | ||
718 | |||
719 | @property | ||
720 | def apparent_encoding(self): | ||
721 | """The apparent encoding, provided by the chardet library.""" | ||
722 | return chardet.detect(self.content)['encoding'] | ||
723 | |||
724 | def iter_content(self, chunk_size=1, decode_unicode=False): | ||
725 | """Iterates over the response data. When stream=True is set on the | ||
726 | request, this avoids reading the content at once into memory for | ||
727 | large responses. The chunk size is the number of bytes it should | ||
728 | read into memory. This is not necessarily the length of each item | ||
729 | returned as decoding can take place. | ||
730 | |||
731 | chunk_size must be of type int or None. A value of None will | ||
732 | function differently depending on the value of `stream`. | ||
733 | stream=True will read data as it arrives in whatever size the | ||
734 | chunks are received. If stream=False, data is returned as | ||
735 | a single chunk. | ||
736 | |||
737 | If decode_unicode is True, content will be decoded using the best | ||
738 | available encoding based on the response. | ||
739 | """ | ||
740 | |||
741 | def generate(): | ||
742 | # Special case for urllib3. | ||
743 | if hasattr(self.raw, 'stream'): | ||
744 | try: | ||
745 | for chunk in self.raw.stream(chunk_size, decode_content=True): | ||
746 | yield chunk | ||
747 | except ProtocolError as e: | ||
748 | raise ChunkedEncodingError(e) | ||
749 | except DecodeError as e: | ||
750 | raise ContentDecodingError(e) | ||
751 | except ReadTimeoutError as e: | ||
752 | raise ConnectionError(e) | ||
753 | else: | ||
754 | # Standard file-like object. | ||
755 | while True: | ||
756 | chunk = self.raw.read(chunk_size) | ||
757 | if not chunk: | ||
758 | break | ||
759 | yield chunk | ||
760 | |||
761 | self._content_consumed = True | ||
762 | |||
763 | if self._content_consumed and isinstance(self._content, bool): | ||
764 | raise StreamConsumedError() | ||
765 | elif chunk_size is not None and not isinstance(chunk_size, int): | ||
766 | raise TypeError("chunk_size must be an int, it is instead a %s." % type(chunk_size)) | ||
767 | # simulate reading small chunks of the content | ||
768 | reused_chunks = iter_slices(self._content, chunk_size) | ||
769 | |||
770 | stream_chunks = generate() | ||
771 | |||
772 | chunks = reused_chunks if self._content_consumed else stream_chunks | ||
773 | |||
774 | if decode_unicode: | ||
775 | chunks = stream_decode_response_unicode(chunks, self) | ||
776 | |||
777 | return chunks | ||
778 | |||
779 | def iter_lines(self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=None, delimiter=None): | ||
780 | """Iterates over the response data, one line at a time. When | ||
781 | stream=True is set on the request, this avoids reading the | ||
782 | content at once into memory for large responses. | ||
783 | |||
784 | .. note:: This method is not reentrant safe. | ||
785 | """ | ||
786 | |||
787 | pending = None | ||
788 | |||
789 | for chunk in self.iter_content(chunk_size=chunk_size, decode_unicode=decode_unicode): | ||
790 | |||
791 | if pending is not None: | ||
792 | chunk = pending + chunk | ||
793 | |||
794 | if delimiter: | ||
795 | lines = chunk.split(delimiter) | ||
796 | else: | ||
797 | lines = chunk.splitlines() | ||
798 | |||
799 | if lines and lines[-1] and chunk and lines[-1][-1] == chunk[-1]: | ||
800 | pending = lines.pop() | ||
801 | else: | ||
802 | pending = None | ||
803 | |||
804 | for line in lines: | ||
805 | yield line | ||
806 | |||
807 | if pending is not None: | ||
808 | yield pending | ||
809 | |||
810 | @property | ||
811 | def content(self): | ||
812 | """Content of the response, in bytes.""" | ||
813 | |||
814 | if self._content is False: | ||
815 | # Read the contents. | ||
816 | if self._content_consumed: | ||
817 | raise RuntimeError( | ||
818 | 'The content for this response was already consumed') | ||
819 | |||
820 | if self.status_code == 0 or self.raw is None: | ||
821 | self._content = None | ||
822 | else: | ||
823 | self._content = bytes().join(self.iter_content(CONTENT_CHUNK_SIZE)) or bytes() | ||
824 | |||
825 | self._content_consumed = True | ||
826 | # don't need to release the connection; that's been handled by urllib3 | ||
827 | # since we exhausted the data. | ||
828 | return self._content | ||
829 | |||
830 | @property | ||
831 | def text(self): | ||
832 | """Content of the response, in unicode. | ||
833 | |||
834 | If Response.encoding is None, encoding will be guessed using | ||
835 | ``chardet``. | ||
836 | |||
837 | The encoding of the response content is determined based solely on HTTP | ||
838 | headers, following RFC 2616 to the letter. If you can take advantage of | ||
839 | non-HTTP knowledge to make a better guess at the encoding, you should | ||
840 | set ``r.encoding`` appropriately before accessing this property. | ||
841 | """ | ||
842 | |||
843 | # Try charset from content-type | ||
844 | content = None | ||
845 | encoding = self.encoding | ||
846 | |||
847 | if not self.content: | ||
848 | return str('') | ||
849 | |||
850 | # Fallback to auto-detected encoding. | ||
851 | if self.encoding is None: | ||
852 | encoding = self.apparent_encoding | ||
853 | |||
854 | # Decode unicode from given encoding. | ||
855 | try: | ||
856 | content = str(self.content, encoding, errors='replace') | ||
857 | except (LookupError, TypeError): | ||
858 | # A LookupError is raised if the encoding was not found which could | ||
859 | # indicate a misspelling or similar mistake. | ||
860 | # | ||
861 | # A TypeError can be raised if encoding is None | ||
862 | # | ||
863 | # So we try blindly encoding. | ||
864 | content = str(self.content, errors='replace') | ||
865 | |||
866 | return content | ||
867 | |||
868 | def json(self, **kwargs): | ||
869 | r"""Returns the json-encoded content of a response, if any. | ||
870 | |||
871 | :param \*\*kwargs: Optional arguments that ``json.loads`` takes. | ||
872 | :raises ValueError: If the response body does not contain valid json. | ||
873 | """ | ||
874 | |||
875 | if not self.encoding and self.content and len(self.content) > 3: | ||
876 | # No encoding set. JSON RFC 4627 section 3 states we should expect | ||
877 | # UTF-8, -16 or -32. Detect which one to use; If the detection or | ||
878 | # decoding fails, fall back to `self.text` (using chardet to make | ||
879 | # a best guess). | ||
880 | encoding = guess_json_utf(self.content) | ||
881 | if encoding is not None: | ||
882 | try: | ||
883 | return complexjson.loads( | ||
884 | self.content.decode(encoding), **kwargs | ||
885 | ) | ||
886 | except UnicodeDecodeError: | ||
887 | # Wrong UTF codec detected; usually because it's not UTF-8 | ||
888 | # but some other 8-bit codec. This is an RFC violation, | ||
889 | # and the server didn't bother to tell us what codec *was* | ||
890 | # used. | ||
891 | pass | ||
892 | return complexjson.loads(self.text, **kwargs) | ||
893 | |||
894 | @property | ||
895 | def links(self): | ||
896 | """Returns the parsed header links of the response, if any.""" | ||
897 | |||
898 | header = self.headers.get('link') | ||
899 | |||
900 | # l = MultiDict() | ||
901 | l = {} | ||
902 | |||
903 | if header: | ||
904 | links = parse_header_links(header) | ||
905 | |||
906 | for link in links: | ||
907 | key = link.get('rel') or link.get('url') | ||
908 | l[key] = link | ||
909 | |||
910 | return l | ||
911 | |||
912 | def raise_for_status(self): | ||
913 | """Raises stored :class:`HTTPError`, if one occurred.""" | ||
914 | |||
915 | http_error_msg = '' | ||
916 | if isinstance(self.reason, bytes): | ||
917 | # We attempt to decode utf-8 first because some servers | ||
918 | # choose to localize their reason strings. If the string | ||
919 | # isn't utf-8, we fall back to iso-8859-1 for all other | ||
920 | # encodings. (See PR #3538) | ||
921 | try: | ||
922 | reason = self.reason.decode('utf-8') | ||
923 | except UnicodeDecodeError: | ||
924 | reason = self.reason.decode('iso-8859-1') | ||
925 | else: | ||
926 | reason = self.reason | ||
927 | |||
928 | if 400 <= self.status_code < 500: | ||
929 | http_error_msg = u'%s Client Error: %s for url: %s' % (self.status_code, reason, self.url) | ||
930 | |||
931 | elif 500 <= self.status_code < 600: | ||
932 | http_error_msg = u'%s Server Error: %s for url: %s' % (self.status_code, reason, self.url) | ||
933 | |||
934 | if http_error_msg: | ||
935 | raise HTTPError(http_error_msg, response=self) | ||
936 | |||
937 | def close(self): | ||
938 | """Releases the connection back to the pool. Once this method has been | ||
939 | called the underlying ``raw`` object must not be accessed again. | ||
940 | |||
941 | *Note: Should not normally need to be called explicitly.* | ||
942 | """ | ||
943 | if not self._content_consumed: | ||
944 | self.raw.close() | ||
945 | |||
946 | release_conn = getattr(self.raw, 'release_conn', None) | ||
947 | if release_conn is not None: | ||
948 | release_conn() | ||