aboutsummaryrefslogtreecommitdiff
path: root/requests/sessions.py
diff options
context:
space:
mode:
authorSVN-Git Migration <python-modules-team@lists.alioth.debian.org>2015-10-08 13:41:28 -0700
committerSVN-Git Migration <python-modules-team@lists.alioth.debian.org>2015-10-08 13:41:28 -0700
commit653256249d44c67a0852d57a166948a9dc712ef4 (patch)
tree91efed3ad3640d3949be638ad4c4e45a63fd3864 /requests/sessions.py
parentc6ee35e00c5709435b3a6b664c44fceb70a918c6 (diff)
downloadpython-requests-653256249d44c67a0852d57a166948a9dc712ef4.tar
python-requests-653256249d44c67a0852d57a166948a9dc712ef4.tar.gz
Imported Upstream version 1.2.3
Diffstat (limited to 'requests/sessions.py')
-rw-r--r--requests/sessions.py126
1 files changed, 56 insertions, 70 deletions
diff --git a/requests/sessions.py b/requests/sessions.py
index de0d9d6..f4aeeee 100644
--- a/requests/sessions.py
+++ b/requests/sessions.py
@@ -9,16 +9,17 @@ requests (cookies, auth, proxies).
"""
import os
+from collections import Mapping
from datetime import datetime
-from .compat import cookielib
-from .cookies import cookiejar_from_dict
+from .compat import cookielib, OrderedDict, urljoin, urlparse
+from .cookies import cookiejar_from_dict, extract_cookies_to_jar, RequestsCookieJar
from .models import Request, PreparedRequest
from .hooks import default_hooks, dispatch_hook
-from .utils import from_key_val_list, default_headers
+from .utils import to_key_val_list, default_headers
from .exceptions import TooManyRedirects, InvalidSchema
+from .structures import CaseInsensitiveDict
-from .compat import urlparse, urljoin
from .adapters import HTTPAdapter
from .utils import requote_uri, get_environ_proxies, get_netrc_auth
@@ -33,49 +34,35 @@ REDIRECT_STATI = (
DEFAULT_REDIRECT_LIMIT = 30
-def merge_kwargs(local_kwarg, default_kwarg):
- """Merges kwarg dictionaries.
-
- If a local key in the dictionary is set to None, it will be removed.
+def merge_setting(request_setting, session_setting, dict_class=OrderedDict):
+ """
+ Determines appropriate setting for a given request, taking into account the
+ explicit setting on that request, and the setting in the session. If a
+ setting is a dictionary, they will be merged together using `dict_class`
"""
- if default_kwarg is None:
- return local_kwarg
-
- if isinstance(local_kwarg, str):
- return local_kwarg
-
- if local_kwarg is None:
- return default_kwarg
-
- # Bypass if not a dictionary (e.g. timeout)
- if not hasattr(default_kwarg, 'items'):
- return local_kwarg
+ if session_setting is None:
+ return request_setting
- default_kwarg = from_key_val_list(default_kwarg)
- local_kwarg = from_key_val_list(local_kwarg)
+ if request_setting is None:
+ return session_setting
- # Update new values in a case-insensitive way
- def get_original_key(original_keys, new_key):
- """
- Finds the key from original_keys that case-insensitive matches new_key.
- """
- for original_key in original_keys:
- if key.lower() == original_key.lower():
- return original_key
- return new_key
+ # Bypass if not a dictionary (e.g. verify)
+ if not (
+ isinstance(session_setting, Mapping) and
+ isinstance(request_setting, Mapping)
+ ):
+ return request_setting
- kwargs = default_kwarg.copy()
- original_keys = kwargs.keys()
- for key, value in local_kwarg.items():
- kwargs[get_original_key(original_keys, key)] = value
+ merged_setting = dict_class(to_key_val_list(session_setting))
+ merged_setting.update(to_key_val_list(request_setting))
# Remove keys that are set to None.
- for (k, v) in local_kwarg.items():
+ for (k, v) in request_setting.items():
if v is None:
- del kwargs[k]
+ del merged_setting[k]
- return kwargs
+ return merged_setting
class SessionRedirectMixin(object):
@@ -91,10 +78,6 @@ class SessionRedirectMixin(object):
prepared_request.method = req.method
prepared_request.url = req.url
- cookiejar = cookiejar_from_dict({})
- cookiejar.update(self.cookies)
- cookiejar.update(resp.cookies)
-
# ((resp.status_code is codes.see_other))
while (('location' in resp.headers and resp.status_code in REDIRECT_STATI)):
@@ -116,9 +99,11 @@ class SessionRedirectMixin(object):
# Facilitate non-RFC2616-compliant 'location' headers
# (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource')
+ # Compliant with RFC3986, we percent encode the url.
if not urlparse(url).netloc:
- # Compliant with RFC3986, we percent encode the url.
url = urljoin(resp.url, requote_uri(url))
+ else:
+ url = requote_uri(url)
prepared_request.url = url
@@ -129,7 +114,7 @@ class SessionRedirectMixin(object):
# Do what the browsers do, despite standards...
if (resp.status_code in (codes.moved, codes.found) and
- prepared_request.method == 'POST'):
+ prepared_request.method not in ('GET', 'HEAD')):
method = 'GET'
prepared_request.method = method
@@ -147,7 +132,7 @@ class SessionRedirectMixin(object):
except KeyError:
pass
- prepared_request.prepare_cookies(cookiejar)
+ prepared_request.prepare_cookies(self.cookies)
resp = self.send(
prepared_request,
@@ -159,13 +144,11 @@ class SessionRedirectMixin(object):
allow_redirects=False,
)
- cookiejar.update(resp.cookies)
+ extract_cookies_to_jar(self.cookies, prepared_request, resp.raw)
i += 1
yield resp
- resp.cookies.update(cookiejar)
-
class Session(SessionRedirectMixin):
"""A Requests session.
@@ -218,7 +201,8 @@ class Session(SessionRedirectMixin):
#: SSL certificate default.
self.cert = None
- #: Maximum number of redirects to follow.
+ #: Maximum number of redirects allowed. If the request exceeds this
+ #: limit, a :class:`TooManyRedirects` exception is raised.
self.max_redirects = DEFAULT_REDIRECT_LIMIT
#: Should we trust the environment?
@@ -228,9 +212,9 @@ class Session(SessionRedirectMixin):
self.cookies = cookiejar_from_dict({})
# Default connection adapters.
- self.adapters = {}
- self.mount('http://', HTTPAdapter())
+ self.adapters = OrderedDict()
self.mount('https://', HTTPAdapter())
+ self.mount('http://', HTTPAdapter())
def __enter__(self):
return self
@@ -274,12 +258,8 @@ class Session(SessionRedirectMixin):
:param allow_redirects: (optional) Boolean. Set to True by default.
:param proxies: (optional) Dictionary mapping protocol to the URL of
the proxy.
- :param return_response: (optional) If False, an un-sent Request object
- will returned.
- :param config: (optional) A configuration dictionary. See
- ``request.defaults`` for allowed keys and their default values.
- :param prefetch: (optional) whether to immediately download the response
- content. Defaults to ``True``.
+ :param stream: (optional) whether to immediately download the response
+ content. Defaults to ``False``.
:param verify: (optional) if ``True``, the SSL cert will be verified.
A CA_BUNDLE path can also be provided.
:param cert: (optional) if String, path to ssl client cert file (.pem).
@@ -294,7 +274,8 @@ class Session(SessionRedirectMixin):
cookies = cookiejar_from_dict(cookies)
# Merge with session cookies
- merged_cookies = self.cookies.copy()
+ merged_cookies = RequestsCookieJar()
+ merged_cookies.update(self.cookies)
merged_cookies.update(cookies)
cookies = merged_cookies
@@ -318,14 +299,14 @@ class Session(SessionRedirectMixin):
verify = os.environ.get('CURL_CA_BUNDLE')
# Merge all the kwargs.
- params = merge_kwargs(params, self.params)
- headers = merge_kwargs(headers, self.headers)
- auth = merge_kwargs(auth, self.auth)
- proxies = merge_kwargs(proxies, self.proxies)
- hooks = merge_kwargs(hooks, self.hooks)
- stream = merge_kwargs(stream, self.stream)
- verify = merge_kwargs(verify, self.verify)
- cert = merge_kwargs(cert, self.cert)
+ params = merge_setting(params, self.params)
+ headers = merge_setting(headers, self.headers, dict_class=CaseInsensitiveDict)
+ auth = merge_setting(auth, self.auth)
+ proxies = merge_setting(proxies, self.proxies)
+ hooks = merge_setting(hooks, self.hooks)
+ stream = merge_setting(stream, self.stream)
+ verify = merge_setting(verify, self.verify)
+ cert = merge_setting(cert, self.cert)
# Create the Request.
req = Request()
@@ -353,9 +334,6 @@ class Session(SessionRedirectMixin):
}
resp = self.send(prep, **send_kwargs)
- # Persist cookies.
- self.cookies.update(resp.cookies)
-
return resp
def get(self, url, **kwargs):
@@ -464,6 +442,9 @@ class Session(SessionRedirectMixin):
# Response manipulation hooks
r = dispatch_hook('response', hooks, r, **kwargs)
+ # Persist cookies
+ extract_cookies_to_jar(self.cookies, request, r.raw)
+
# Redirect resolving generator.
gen = self.resolve_redirects(r, request, stream=stream,
timeout=timeout, verify=verify, cert=cert,
@@ -498,8 +479,13 @@ class Session(SessionRedirectMixin):
v.close()
def mount(self, prefix, adapter):
- """Registers a connection adapter to a prefix."""
+ """Registers a connection adapter to a prefix.
+
+ Adapters are sorted in descending order by key length."""
self.adapters[prefix] = adapter
+ keys_to_move = [k for k in self.adapters if len(k) < len(prefix)]
+ for key in keys_to_move:
+ self.adapters[key] = self.adapters.pop(key)
def __getstate__(self):
return dict((attr, getattr(self, attr, None)) for attr in self.__attrs__)