diff options
author | Shubham Saini <shubham6405@gmail.com> | 2019-08-05 08:32:33 +0000 |
---|---|---|
committer | Shubham Saini <shubham6405@gmail.com> | 2019-08-05 08:32:33 +0000 |
commit | 227b2d30a8675b44918f9d9ca89b24144a938215 (patch) | |
tree | 9f8e6a28724514b6fdf463a9ab2067a7ef309b72 /venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/requests/sessions.py | |
parent | 842a8cfbbbdb1f92889d892e4859dbd5d40c5be8 (diff) |
removing venv files
Diffstat (limited to 'venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/requests/sessions.py')
-rw-r--r-- | venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/requests/sessions.py | 737 |
1 files changed, 0 insertions, 737 deletions
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/requests/sessions.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/requests/sessions.py deleted file mode 100644 index d8eafa8..0000000 --- a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/requests/sessions.py +++ /dev/null | |||
@@ -1,737 +0,0 @@ | |||
1 | # -*- coding: utf-8 -*- | ||
2 | |||
3 | """ | ||
4 | requests.session | ||
5 | ~~~~~~~~~~~~~~~~ | ||
6 | |||
7 | This module provides a Session object to manage and persist settings across | ||
8 | requests (cookies, auth, proxies). | ||
9 | """ | ||
10 | import os | ||
11 | import platform | ||
12 | import time | ||
13 | from collections import Mapping | ||
14 | from datetime import timedelta | ||
15 | |||
16 | from .auth import _basic_auth_str | ||
17 | from .compat import cookielib, is_py3, OrderedDict, urljoin, urlparse | ||
18 | from .cookies import ( | ||
19 | cookiejar_from_dict, extract_cookies_to_jar, RequestsCookieJar, merge_cookies) | ||
20 | from .models import Request, PreparedRequest, DEFAULT_REDIRECT_LIMIT | ||
21 | from .hooks import default_hooks, dispatch_hook | ||
22 | from ._internal_utils import to_native_string | ||
23 | from .utils import to_key_val_list, default_headers | ||
24 | from .exceptions import ( | ||
25 | TooManyRedirects, InvalidSchema, ChunkedEncodingError, ContentDecodingError) | ||
26 | |||
27 | from .structures import CaseInsensitiveDict | ||
28 | from .adapters import HTTPAdapter | ||
29 | |||
30 | from .utils import ( | ||
31 | requote_uri, get_environ_proxies, get_netrc_auth, should_bypass_proxies, | ||
32 | get_auth_from_url, rewind_body | ||
33 | ) | ||
34 | |||
35 | from .status_codes import codes | ||
36 | |||
37 | # formerly defined here, reexposed here for backward compatibility | ||
38 | from .models import REDIRECT_STATI | ||
39 | |||
40 | # Preferred clock, based on which one is more accurate on a given system. | ||
41 | if platform.system() == 'Windows': | ||
42 | try: # Python 3.3+ | ||
43 | preferred_clock = time.perf_counter | ||
44 | except AttributeError: # Earlier than Python 3. | ||
45 | preferred_clock = time.clock | ||
46 | else: | ||
47 | preferred_clock = time.time | ||
48 | |||
49 | |||
50 | def merge_setting(request_setting, session_setting, dict_class=OrderedDict): | ||
51 | """Determines appropriate setting for a given request, taking into account | ||
52 | the explicit setting on that request, and the setting in the session. If a | ||
53 | setting is a dictionary, they will be merged together using `dict_class` | ||
54 | """ | ||
55 | |||
56 | if session_setting is None: | ||
57 | return request_setting | ||
58 | |||
59 | if request_setting is None: | ||
60 | return session_setting | ||
61 | |||
62 | # Bypass if not a dictionary (e.g. verify) | ||
63 | if not ( | ||
64 | isinstance(session_setting, Mapping) and | ||
65 | isinstance(request_setting, Mapping) | ||
66 | ): | ||
67 | return request_setting | ||
68 | |||
69 | merged_setting = dict_class(to_key_val_list(session_setting)) | ||
70 | merged_setting.update(to_key_val_list(request_setting)) | ||
71 | |||
72 | # Remove keys that are set to None. Extract keys first to avoid altering | ||
73 | # the dictionary during iteration. | ||
74 | none_keys = [k for (k, v) in merged_setting.items() if v is None] | ||
75 | for key in none_keys: | ||
76 | del merged_setting[key] | ||
77 | |||
78 | return merged_setting | ||
79 | |||
80 | |||
81 | def merge_hooks(request_hooks, session_hooks, dict_class=OrderedDict): | ||
82 | """Properly merges both requests and session hooks. | ||
83 | |||
84 | This is necessary because when request_hooks == {'response': []}, the | ||
85 | merge breaks Session hooks entirely. | ||
86 | """ | ||
87 | if session_hooks is None or session_hooks.get('response') == []: | ||
88 | return request_hooks | ||
89 | |||
90 | if request_hooks is None or request_hooks.get('response') == []: | ||
91 | return session_hooks | ||
92 | |||
93 | return merge_setting(request_hooks, session_hooks, dict_class) | ||
94 | |||
95 | |||
96 | class SessionRedirectMixin(object): | ||
97 | |||
98 | def get_redirect_target(self, resp): | ||
99 | """Receives a Response. Returns a redirect URI or ``None``""" | ||
100 | # Due to the nature of how requests processes redirects this method will | ||
101 | # be called at least once upon the original response and at least twice | ||
102 | # on each subsequent redirect response (if any). | ||
103 | # If a custom mixin is used to handle this logic, it may be advantageous | ||
104 | # to cache the redirect location onto the response object as a private | ||
105 | # attribute. | ||
106 | if resp.is_redirect: | ||
107 | location = resp.headers['location'] | ||
108 | # Currently the underlying http module on py3 decode headers | ||
109 | # in latin1, but empirical evidence suggests that latin1 is very | ||
110 | # rarely used with non-ASCII characters in HTTP headers. | ||
111 | # It is more likely to get UTF8 header rather than latin1. | ||
112 | # This causes incorrect handling of UTF8 encoded location headers. | ||
113 | # To solve this, we re-encode the location in latin1. | ||
114 | if is_py3: | ||
115 | location = location.encode('latin1') | ||
116 | return to_native_string(location, 'utf8') | ||
117 | return None | ||
118 | |||
119 | def resolve_redirects(self, resp, req, stream=False, timeout=None, | ||
120 | verify=True, cert=None, proxies=None, yield_requests=False, **adapter_kwargs): | ||
121 | """Receives a Response. Returns a generator of Responses or Requests.""" | ||
122 | |||
123 | hist = [] # keep track of history | ||
124 | |||
125 | url = self.get_redirect_target(resp) | ||
126 | while url: | ||
127 | prepared_request = req.copy() | ||
128 | |||
129 | # Update history and keep track of redirects. | ||
130 | # resp.history must ignore the original request in this loop | ||
131 | hist.append(resp) | ||
132 | resp.history = hist[1:] | ||
133 | |||
134 | try: | ||
135 | resp.content # Consume socket so it can be released | ||
136 | except (ChunkedEncodingError, ContentDecodingError, RuntimeError): | ||
137 | resp.raw.read(decode_content=False) | ||
138 | |||
139 | if len(resp.history) >= self.max_redirects: | ||
140 | raise TooManyRedirects('Exceeded %s redirects.' % self.max_redirects, response=resp) | ||
141 | |||
142 | # Release the connection back into the pool. | ||
143 | resp.close() | ||
144 | |||
145 | # Handle redirection without scheme (see: RFC 1808 Section 4) | ||
146 | if url.startswith('//'): | ||
147 | parsed_rurl = urlparse(resp.url) | ||
148 | url = '%s:%s' % (to_native_string(parsed_rurl.scheme), url) | ||
149 | |||
150 | # The scheme should be lower case... | ||
151 | parsed = urlparse(url) | ||
152 | url = parsed.geturl() | ||
153 | |||
154 | # Facilitate relative 'location' headers, as allowed by RFC 7231. | ||
155 | # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource') | ||
156 | # Compliant with RFC3986, we percent encode the url. | ||
157 | if not parsed.netloc: | ||
158 | url = urljoin(resp.url, requote_uri(url)) | ||
159 | else: | ||
160 | url = requote_uri(url) | ||
161 | |||
162 | prepared_request.url = to_native_string(url) | ||
163 | |||
164 | self.rebuild_method(prepared_request, resp) | ||
165 | |||
166 | # https://github.com/requests/requests/issues/1084 | ||
167 | if resp.status_code not in (codes.temporary_redirect, codes.permanent_redirect): | ||
168 | # https://github.com/requests/requests/issues/3490 | ||
169 | purged_headers = ('Content-Length', 'Content-Type', 'Transfer-Encoding') | ||
170 | for header in purged_headers: | ||
171 | prepared_request.headers.pop(header, None) | ||
172 | prepared_request.body = None | ||
173 | |||
174 | headers = prepared_request.headers | ||
175 | try: | ||
176 | del headers['Cookie'] | ||
177 | except KeyError: | ||
178 | pass | ||
179 | |||
180 | # Extract any cookies sent on the response to the cookiejar | ||
181 | # in the new request. Because we've mutated our copied prepared | ||
182 | # request, use the old one that we haven't yet touched. | ||
183 | extract_cookies_to_jar(prepared_request._cookies, req, resp.raw) | ||
184 | merge_cookies(prepared_request._cookies, self.cookies) | ||
185 | prepared_request.prepare_cookies(prepared_request._cookies) | ||
186 | |||
187 | # Rebuild auth and proxy information. | ||
188 | proxies = self.rebuild_proxies(prepared_request, proxies) | ||
189 | self.rebuild_auth(prepared_request, resp) | ||
190 | |||
191 | # A failed tell() sets `_body_position` to `object()`. This non-None | ||
192 | # value ensures `rewindable` will be True, allowing us to raise an | ||
193 | # UnrewindableBodyError, instead of hanging the connection. | ||
194 | rewindable = ( | ||
195 | prepared_request._body_position is not None and | ||
196 | ('Content-Length' in headers or 'Transfer-Encoding' in headers) | ||
197 | ) | ||
198 | |||
199 | # Attempt to rewind consumed file-like object. | ||
200 | if rewindable: | ||
201 | rewind_body(prepared_request) | ||
202 | |||
203 | # Override the original request. | ||
204 | req = prepared_request | ||
205 | |||
206 | if yield_requests: | ||
207 | yield req | ||
208 | else: | ||
209 | |||
210 | resp = self.send( | ||
211 | req, | ||
212 | stream=stream, | ||
213 | timeout=timeout, | ||
214 | verify=verify, | ||
215 | cert=cert, | ||
216 | proxies=proxies, | ||
217 | allow_redirects=False, | ||
218 | **adapter_kwargs | ||
219 | ) | ||
220 | |||
221 | extract_cookies_to_jar(self.cookies, prepared_request, resp.raw) | ||
222 | |||
223 | # extract redirect url, if any, for the next loop | ||
224 | url = self.get_redirect_target(resp) | ||
225 | yield resp | ||
226 | |||
227 | def rebuild_auth(self, prepared_request, response): | ||
228 | """When being redirected we may want to strip authentication from the | ||
229 | request to avoid leaking credentials. This method intelligently removes | ||
230 | and reapplies authentication where possible to avoid credential loss. | ||
231 | """ | ||
232 | headers = prepared_request.headers | ||
233 | url = prepared_request.url | ||
234 | |||
235 | if 'Authorization' in headers: | ||
236 | # If we get redirected to a new host, we should strip out any | ||
237 | # authentication headers. | ||
238 | original_parsed = urlparse(response.request.url) | ||
239 | redirect_parsed = urlparse(url) | ||
240 | |||
241 | if (original_parsed.hostname != redirect_parsed.hostname): | ||
242 | del headers['Authorization'] | ||
243 | |||
244 | # .netrc might have more auth for us on our new host. | ||
245 | new_auth = get_netrc_auth(url) if self.trust_env else None | ||
246 | if new_auth is not None: | ||
247 | prepared_request.prepare_auth(new_auth) | ||
248 | |||
249 | return | ||
250 | |||
251 | def rebuild_proxies(self, prepared_request, proxies): | ||
252 | """This method re-evaluates the proxy configuration by considering the | ||
253 | environment variables. If we are redirected to a URL covered by | ||
254 | NO_PROXY, we strip the proxy configuration. Otherwise, we set missing | ||
255 | proxy keys for this URL (in case they were stripped by a previous | ||
256 | redirect). | ||
257 | |||
258 | This method also replaces the Proxy-Authorization header where | ||
259 | necessary. | ||
260 | |||
261 | :rtype: dict | ||
262 | """ | ||
263 | proxies = proxies if proxies is not None else {} | ||
264 | headers = prepared_request.headers | ||
265 | url = prepared_request.url | ||
266 | scheme = urlparse(url).scheme | ||
267 | new_proxies = proxies.copy() | ||
268 | no_proxy = proxies.get('no_proxy') | ||
269 | |||
270 | bypass_proxy = should_bypass_proxies(url, no_proxy=no_proxy) | ||
271 | if self.trust_env and not bypass_proxy: | ||
272 | environ_proxies = get_environ_proxies(url, no_proxy=no_proxy) | ||
273 | |||
274 | proxy = environ_proxies.get(scheme, environ_proxies.get('all')) | ||
275 | |||
276 | if proxy: | ||
277 | new_proxies.setdefault(scheme, proxy) | ||
278 | |||
279 | if 'Proxy-Authorization' in headers: | ||
280 | del headers['Proxy-Authorization'] | ||
281 | |||
282 | try: | ||
283 | username, password = get_auth_from_url(new_proxies[scheme]) | ||
284 | except KeyError: | ||
285 | username, password = None, None | ||
286 | |||
287 | if username and password: | ||
288 | headers['Proxy-Authorization'] = _basic_auth_str(username, password) | ||
289 | |||
290 | return new_proxies | ||
291 | |||
292 | def rebuild_method(self, prepared_request, response): | ||
293 | """When being redirected we may want to change the method of the request | ||
294 | based on certain specs or browser behavior. | ||
295 | """ | ||
296 | method = prepared_request.method | ||
297 | |||
298 | # http://tools.ietf.org/html/rfc7231#section-6.4.4 | ||
299 | if response.status_code == codes.see_other and method != 'HEAD': | ||
300 | method = 'GET' | ||
301 | |||
302 | # Do what the browsers do, despite standards... | ||
303 | # First, turn 302s into GETs. | ||
304 | if response.status_code == codes.found and method != 'HEAD': | ||
305 | method = 'GET' | ||
306 | |||
307 | # Second, if a POST is responded to with a 301, turn it into a GET. | ||
308 | # This bizarre behaviour is explained in Issue 1704. | ||
309 | if response.status_code == codes.moved and method == 'POST': | ||
310 | method = 'GET' | ||
311 | |||
312 | prepared_request.method = method | ||
313 | |||
314 | |||
315 | class Session(SessionRedirectMixin): | ||
316 | """A Requests session. | ||
317 | |||
318 | Provides cookie persistence, connection-pooling, and configuration. | ||
319 | |||
320 | Basic Usage:: | ||
321 | |||
322 | >>> import requests | ||
323 | >>> s = requests.Session() | ||
324 | >>> s.get('http://httpbin.org/get') | ||
325 | <Response [200]> | ||
326 | |||
327 | Or as a context manager:: | ||
328 | |||
329 | >>> with requests.Session() as s: | ||
330 | >>> s.get('http://httpbin.org/get') | ||
331 | <Response [200]> | ||
332 | """ | ||
333 | |||
334 | __attrs__ = [ | ||
335 | 'headers', 'cookies', 'auth', 'proxies', 'hooks', 'params', 'verify', | ||
336 | 'cert', 'prefetch', 'adapters', 'stream', 'trust_env', | ||
337 | 'max_redirects', | ||
338 | ] | ||
339 | |||
340 | def __init__(self): | ||
341 | |||
342 | #: A case-insensitive dictionary of headers to be sent on each | ||
343 | #: :class:`Request <Request>` sent from this | ||
344 | #: :class:`Session <Session>`. | ||
345 | self.headers = default_headers() | ||
346 | |||
347 | #: Default Authentication tuple or object to attach to | ||
348 | #: :class:`Request <Request>`. | ||
349 | self.auth = None | ||
350 | |||
351 | #: Dictionary mapping protocol or protocol and host to the URL of the proxy | ||
352 | #: (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) to | ||
353 | #: be used on each :class:`Request <Request>`. | ||
354 | self.proxies = {} | ||
355 | |||
356 | #: Event-handling hooks. | ||
357 | self.hooks = default_hooks() | ||
358 | |||
359 | #: Dictionary of querystring data to attach to each | ||
360 | #: :class:`Request <Request>`. The dictionary values may be lists for | ||
361 | #: representing multivalued query parameters. | ||
362 | self.params = {} | ||
363 | |||
364 | #: Stream response content default. | ||
365 | self.stream = False | ||
366 | |||
367 | #: SSL Verification default. | ||
368 | self.verify = True | ||
369 | |||
370 | #: SSL client certificate default, if String, path to ssl client | ||
371 | #: cert file (.pem). If Tuple, ('cert', 'key') pair. | ||
372 | self.cert = None | ||
373 | |||
374 | #: Maximum number of redirects allowed. If the request exceeds this | ||
375 | #: limit, a :class:`TooManyRedirects` exception is raised. | ||
376 | #: This defaults to requests.models.DEFAULT_REDIRECT_LIMIT, which is | ||
377 | #: 30. | ||
378 | self.max_redirects = DEFAULT_REDIRECT_LIMIT | ||
379 | |||
380 | #: Trust environment settings for proxy configuration, default | ||
381 | #: authentication and similar. | ||
382 | self.trust_env = True | ||
383 | |||
384 | #: A CookieJar containing all currently outstanding cookies set on this | ||
385 | #: session. By default it is a | ||
386 | #: :class:`RequestsCookieJar <requests.cookies.RequestsCookieJar>`, but | ||
387 | #: may be any other ``cookielib.CookieJar`` compatible object. | ||
388 | self.cookies = cookiejar_from_dict({}) | ||
389 | |||
390 | # Default connection adapters. | ||
391 | self.adapters = OrderedDict() | ||
392 | self.mount('https://', HTTPAdapter()) | ||
393 | self.mount('http://', HTTPAdapter()) | ||
394 | |||
395 | def __enter__(self): | ||
396 | return self | ||
397 | |||
398 | def __exit__(self, *args): | ||
399 | self.close() | ||
400 | |||
401 | def prepare_request(self, request): | ||
402 | """Constructs a :class:`PreparedRequest <PreparedRequest>` for | ||
403 | transmission and returns it. The :class:`PreparedRequest` has settings | ||
404 | merged from the :class:`Request <Request>` instance and those of the | ||
405 | :class:`Session`. | ||
406 | |||
407 | :param request: :class:`Request` instance to prepare with this | ||
408 | session's settings. | ||
409 | :rtype: requests.PreparedRequest | ||
410 | """ | ||
411 | cookies = request.cookies or {} | ||
412 | |||
413 | # Bootstrap CookieJar. | ||
414 | if not isinstance(cookies, cookielib.CookieJar): | ||
415 | cookies = cookiejar_from_dict(cookies) | ||
416 | |||
417 | # Merge with session cookies | ||
418 | merged_cookies = merge_cookies( | ||
419 | merge_cookies(RequestsCookieJar(), self.cookies), cookies) | ||
420 | |||
421 | # Set environment's basic authentication if not explicitly set. | ||
422 | auth = request.auth | ||
423 | if self.trust_env and not auth and not self.auth: | ||
424 | auth = get_netrc_auth(request.url) | ||
425 | |||
426 | p = PreparedRequest() | ||
427 | p.prepare( | ||
428 | method=request.method.upper(), | ||
429 | url=request.url, | ||
430 | files=request.files, | ||
431 | data=request.data, | ||
432 | json=request.json, | ||
433 | headers=merge_setting(request.headers, self.headers, dict_class=CaseInsensitiveDict), | ||
434 | params=merge_setting(request.params, self.params), | ||
435 | auth=merge_setting(auth, self.auth), | ||
436 | cookies=merged_cookies, | ||
437 | hooks=merge_hooks(request.hooks, self.hooks), | ||
438 | ) | ||
439 | return p | ||
440 | |||
441 | def request(self, method, url, | ||
442 | params=None, data=None, headers=None, cookies=None, files=None, | ||
443 | auth=None, timeout=None, allow_redirects=True, proxies=None, | ||
444 | hooks=None, stream=None, verify=None, cert=None, json=None): | ||
445 | """Constructs a :class:`Request <Request>`, prepares it and sends it. | ||
446 | Returns :class:`Response <Response>` object. | ||
447 | |||
448 | :param method: method for the new :class:`Request` object. | ||
449 | :param url: URL for the new :class:`Request` object. | ||
450 | :param params: (optional) Dictionary or bytes to be sent in the query | ||
451 | string for the :class:`Request`. | ||
452 | :param data: (optional) Dictionary, bytes, or file-like object to send | ||
453 | in the body of the :class:`Request`. | ||
454 | :param json: (optional) json to send in the body of the | ||
455 | :class:`Request`. | ||
456 | :param headers: (optional) Dictionary of HTTP Headers to send with the | ||
457 | :class:`Request`. | ||
458 | :param cookies: (optional) Dict or CookieJar object to send with the | ||
459 | :class:`Request`. | ||
460 | :param files: (optional) Dictionary of ``'filename': file-like-objects`` | ||
461 | for multipart encoding upload. | ||
462 | :param auth: (optional) Auth tuple or callable to enable | ||
463 | Basic/Digest/Custom HTTP Auth. | ||
464 | :param timeout: (optional) How long to wait for the server to send | ||
465 | data before giving up, as a float, or a :ref:`(connect timeout, | ||
466 | read timeout) <timeouts>` tuple. | ||
467 | :type timeout: float or tuple | ||
468 | :param allow_redirects: (optional) Set to True by default. | ||
469 | :type allow_redirects: bool | ||
470 | :param proxies: (optional) Dictionary mapping protocol or protocol and | ||
471 | hostname to the URL of the proxy. | ||
472 | :param stream: (optional) whether to immediately download the response | ||
473 | content. Defaults to ``False``. | ||
474 | :param verify: (optional) Either a boolean, in which case it controls whether we verify | ||
475 | the server's TLS certificate, or a string, in which case it must be a path | ||
476 | to a CA bundle to use. Defaults to ``True``. | ||
477 | :param cert: (optional) if String, path to ssl client cert file (.pem). | ||
478 | If Tuple, ('cert', 'key') pair. | ||
479 | :rtype: requests.Response | ||
480 | """ | ||
481 | # Create the Request. | ||
482 | req = Request( | ||
483 | method=method.upper(), | ||
484 | url=url, | ||
485 | headers=headers, | ||
486 | files=files, | ||
487 | data=data or {}, | ||
488 | json=json, | ||
489 | params=params or {}, | ||
490 | auth=auth, | ||
491 | cookies=cookies, | ||
492 | hooks=hooks, | ||
493 | ) | ||
494 | prep = self.prepare_request(req) | ||
495 | |||
496 | proxies = proxies or {} | ||
497 | |||
498 | settings = self.merge_environment_settings( | ||
499 | prep.url, proxies, stream, verify, cert | ||
500 | ) | ||
501 | |||
502 | # Send the request. | ||
503 | send_kwargs = { | ||
504 | 'timeout': timeout, | ||
505 | 'allow_redirects': allow_redirects, | ||
506 | } | ||
507 | send_kwargs.update(settings) | ||
508 | resp = self.send(prep, **send_kwargs) | ||
509 | |||
510 | return resp | ||
511 | |||
512 | def get(self, url, **kwargs): | ||
513 | r"""Sends a GET request. Returns :class:`Response` object. | ||
514 | |||
515 | :param url: URL for the new :class:`Request` object. | ||
516 | :param \*\*kwargs: Optional arguments that ``request`` takes. | ||
517 | :rtype: requests.Response | ||
518 | """ | ||
519 | |||
520 | kwargs.setdefault('allow_redirects', True) | ||
521 | return self.request('GET', url, **kwargs) | ||
522 | |||
523 | def options(self, url, **kwargs): | ||
524 | r"""Sends a OPTIONS request. Returns :class:`Response` object. | ||
525 | |||
526 | :param url: URL for the new :class:`Request` object. | ||
527 | :param \*\*kwargs: Optional arguments that ``request`` takes. | ||
528 | :rtype: requests.Response | ||
529 | """ | ||
530 | |||
531 | kwargs.setdefault('allow_redirects', True) | ||
532 | return self.request('OPTIONS', url, **kwargs) | ||
533 | |||
534 | def head(self, url, **kwargs): | ||
535 | r"""Sends a HEAD request. Returns :class:`Response` object. | ||
536 | |||
537 | :param url: URL for the new :class:`Request` object. | ||
538 | :param \*\*kwargs: Optional arguments that ``request`` takes. | ||
539 | :rtype: requests.Response | ||
540 | """ | ||
541 | |||
542 | kwargs.setdefault('allow_redirects', False) | ||
543 | return self.request('HEAD', url, **kwargs) | ||
544 | |||
545 | def post(self, url, data=None, json=None, **kwargs): | ||
546 | r"""Sends a POST request. Returns :class:`Response` object. | ||
547 | |||
548 | :param url: URL for the new :class:`Request` object. | ||
549 | :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. | ||
550 | :param json: (optional) json to send in the body of the :class:`Request`. | ||
551 | :param \*\*kwargs: Optional arguments that ``request`` takes. | ||
552 | :rtype: requests.Response | ||
553 | """ | ||
554 | |||
555 | return self.request('POST', url, data=data, json=json, **kwargs) | ||
556 | |||
557 | def put(self, url, data=None, **kwargs): | ||
558 | r"""Sends a PUT request. Returns :class:`Response` object. | ||
559 | |||
560 | :param url: URL for the new :class:`Request` object. | ||
561 | :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. | ||
562 | :param \*\*kwargs: Optional arguments that ``request`` takes. | ||
563 | :rtype: requests.Response | ||
564 | """ | ||
565 | |||
566 | return self.request('PUT', url, data=data, **kwargs) | ||
567 | |||
568 | def patch(self, url, data=None, **kwargs): | ||
569 | r"""Sends a PATCH request. Returns :class:`Response` object. | ||
570 | |||
571 | :param url: URL for the new :class:`Request` object. | ||
572 | :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. | ||
573 | :param \*\*kwargs: Optional arguments that ``request`` takes. | ||
574 | :rtype: requests.Response | ||
575 | """ | ||
576 | |||
577 | return self.request('PATCH', url, data=data, **kwargs) | ||
578 | |||
579 | def delete(self, url, **kwargs): | ||
580 | r"""Sends a DELETE request. Returns :class:`Response` object. | ||
581 | |||
582 | :param url: URL for the new :class:`Request` object. | ||
583 | :param \*\*kwargs: Optional arguments that ``request`` takes. | ||
584 | :rtype: requests.Response | ||
585 | """ | ||
586 | |||
587 | return self.request('DELETE', url, **kwargs) | ||
588 | |||
589 | def send(self, request, **kwargs): | ||
590 | """Send a given PreparedRequest. | ||
591 | |||
592 | :rtype: requests.Response | ||
593 | """ | ||
594 | # Set defaults that the hooks can utilize to ensure they always have | ||
595 | # the correct parameters to reproduce the previous request. | ||
596 | kwargs.setdefault('stream', self.stream) | ||
597 | kwargs.setdefault('verify', self.verify) | ||
598 | kwargs.setdefault('cert', self.cert) | ||
599 | kwargs.setdefault('proxies', self.proxies) | ||
600 | |||
601 | # It's possible that users might accidentally send a Request object. | ||
602 | # Guard against that specific failure case. | ||
603 | if isinstance(request, Request): | ||
604 | raise ValueError('You can only send PreparedRequests.') | ||
605 | |||
606 | # Set up variables needed for resolve_redirects and dispatching of hooks | ||
607 | allow_redirects = kwargs.pop('allow_redirects', True) | ||
608 | stream = kwargs.get('stream') | ||
609 | hooks = request.hooks | ||
610 | |||
611 | # Get the appropriate adapter to use | ||
612 | adapter = self.get_adapter(url=request.url) | ||
613 | |||
614 | # Start time (approximately) of the request | ||
615 | start = preferred_clock() | ||
616 | |||
617 | # Send the request | ||
618 | r = adapter.send(request, **kwargs) | ||
619 | |||
620 | # Total elapsed time of the request (approximately) | ||
621 | elapsed = preferred_clock() - start | ||
622 | r.elapsed = timedelta(seconds=elapsed) | ||
623 | |||
624 | # Response manipulation hooks | ||
625 | r = dispatch_hook('response', hooks, r, **kwargs) | ||
626 | |||
627 | # Persist cookies | ||
628 | if r.history: | ||
629 | |||
630 | # If the hooks create history then we want those cookies too | ||
631 | for resp in r.history: | ||
632 | extract_cookies_to_jar(self.cookies, resp.request, resp.raw) | ||
633 | |||
634 | extract_cookies_to_jar(self.cookies, request, r.raw) | ||
635 | |||
636 | # Redirect resolving generator. | ||
637 | gen = self.resolve_redirects(r, request, **kwargs) | ||
638 | |||
639 | # Resolve redirects if allowed. | ||
640 | history = [resp for resp in gen] if allow_redirects else [] | ||
641 | |||
642 | # Shuffle things around if there's history. | ||
643 | if history: | ||
644 | # Insert the first (original) request at the start | ||
645 | history.insert(0, r) | ||
646 | # Get the last request made | ||
647 | r = history.pop() | ||
648 | r.history = history | ||
649 | |||
650 | # If redirects aren't being followed, store the response on the Request for Response.next(). | ||
651 | if not allow_redirects: | ||
652 | try: | ||
653 | r._next = next(self.resolve_redirects(r, request, yield_requests=True, **kwargs)) | ||
654 | except StopIteration: | ||
655 | pass | ||
656 | |||
657 | if not stream: | ||
658 | r.content | ||
659 | |||
660 | return r | ||
661 | |||
662 | def merge_environment_settings(self, url, proxies, stream, verify, cert): | ||
663 | """ | ||
664 | Check the environment and merge it with some settings. | ||
665 | |||
666 | :rtype: dict | ||
667 | """ | ||
668 | # Gather clues from the surrounding environment. | ||
669 | if self.trust_env: | ||
670 | # Set environment's proxies. | ||
671 | no_proxy = proxies.get('no_proxy') if proxies is not None else None | ||
672 | env_proxies = get_environ_proxies(url, no_proxy=no_proxy) | ||
673 | for (k, v) in env_proxies.items(): | ||
674 | proxies.setdefault(k, v) | ||
675 | |||
676 | # Look for requests environment configuration and be compatible | ||
677 | # with cURL. | ||
678 | if verify is True or verify is None: | ||
679 | verify = (os.environ.get('REQUESTS_CA_BUNDLE') or | ||
680 | os.environ.get('CURL_CA_BUNDLE')) | ||
681 | |||
682 | # Merge all the kwargs. | ||
683 | proxies = merge_setting(proxies, self.proxies) | ||
684 | stream = merge_setting(stream, self.stream) | ||
685 | verify = merge_setting(verify, self.verify) | ||
686 | cert = merge_setting(cert, self.cert) | ||
687 | |||
688 | return {'verify': verify, 'proxies': proxies, 'stream': stream, | ||
689 | 'cert': cert} | ||
690 | |||
691 | def get_adapter(self, url): | ||
692 | """ | ||
693 | Returns the appropriate connection adapter for the given URL. | ||
694 | |||
695 | :rtype: requests.adapters.BaseAdapter | ||
696 | """ | ||
697 | for (prefix, adapter) in self.adapters.items(): | ||
698 | |||
699 | if url.lower().startswith(prefix): | ||
700 | return adapter | ||
701 | |||
702 | # Nothing matches :-/ | ||
703 | raise InvalidSchema("No connection adapters were found for '%s'" % url) | ||
704 | |||
705 | def close(self): | ||
706 | """Closes all adapters and as such the session""" | ||
707 | for v in self.adapters.values(): | ||
708 | v.close() | ||
709 | |||
710 | def mount(self, prefix, adapter): | ||
711 | """Registers a connection adapter to a prefix. | ||
712 | |||
713 | Adapters are sorted in descending order by prefix length. | ||
714 | """ | ||
715 | self.adapters[prefix] = adapter | ||
716 | keys_to_move = [k for k in self.adapters if len(k) < len(prefix)] | ||
717 | |||
718 | for key in keys_to_move: | ||
719 | self.adapters[key] = self.adapters.pop(key) | ||
720 | |||
721 | def __getstate__(self): | ||
722 | state = dict((attr, getattr(self, attr, None)) for attr in self.__attrs__) | ||
723 | return state | ||
724 | |||
725 | def __setstate__(self, state): | ||
726 | for attr, value in state.items(): | ||
727 | setattr(self, attr, value) | ||
728 | |||
729 | |||
730 | def session(): | ||
731 | """ | ||
732 | Returns a :class:`Session` for context-management. | ||
733 | |||
734 | :rtype: Session | ||
735 | """ | ||
736 | |||
737 | return Session() | ||