mirror of
https://github.com/kennethreitz/requests3.git
synced 2026-06-05 23:10:16 +00:00
261 lines
7.4 KiB
Python
261 lines
7.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
requests.session
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
This module provides a Session object to manage and persist settings across
|
|
requests (cookies, auth, proxies).
|
|
|
|
"""
|
|
|
|
from copy import deepcopy
|
|
from .compat import cookielib
|
|
from .cookies import cookiejar_from_dict, remove_cookie_by_name
|
|
from .defaults import defaults
|
|
from .models import Request
|
|
from .hooks import dispatch_hook
|
|
from .utils import header_expand, from_key_val_list
|
|
from .packages.urllib3.poolmanager import PoolManager
|
|
|
|
|
|
from .adapters import HTTPAdapter
|
|
|
|
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.
|
|
"""
|
|
|
|
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
|
|
|
|
default_kwarg = from_key_val_list(default_kwarg)
|
|
local_kwarg = from_key_val_list(local_kwarg)
|
|
|
|
# Update new values.
|
|
kwargs = default_kwarg.copy()
|
|
kwargs.update(local_kwarg)
|
|
|
|
# Remove keys that are set to None.
|
|
for (k, v) in local_kwarg.items():
|
|
if v is None:
|
|
del kwargs[k]
|
|
|
|
return kwargs
|
|
|
|
|
|
class Session(object):
|
|
"""A Requests session."""
|
|
|
|
__attrs__ = [
|
|
'headers', 'cookies', 'auth', 'timeout', 'proxies', 'hooks',
|
|
'params', 'config', 'verify', 'cert', 'prefetch']
|
|
|
|
def __init__(self,
|
|
headers=None,
|
|
cookies=None,
|
|
auth=None,
|
|
timeout=None,
|
|
proxies=None,
|
|
hooks=None,
|
|
params=None,
|
|
config=None,
|
|
prefetch=True,
|
|
verify=True,
|
|
cert=None):
|
|
|
|
#: A case-insensitive dictionary of headers to be sent on each
|
|
#: :class:`Request <Request>` sent from this
|
|
#: :class:`Session <Session>`.
|
|
self.headers = from_key_val_list(headers or [])
|
|
|
|
#: Authentication tuple or object to attach to
|
|
#: :class:`Request <Request>`.
|
|
self.auth = auth
|
|
|
|
#: Float describing the timeout of the each :class:`Request <Request>`.
|
|
self.timeout = timeout
|
|
|
|
#: Dictionary mapping protocol to the URL of the proxy (e.g.
|
|
#: {'http': 'foo.bar:3128'}) to be used on each
|
|
#: :class:`Request <Request>`.
|
|
self.proxies = from_key_val_list(proxies or [])
|
|
|
|
#: Event-handling hooks.
|
|
self.hooks = from_key_val_list(hooks or {})
|
|
|
|
#: Dictionary of querystring data to attach to each
|
|
#: :class:`Request <Request>`. The dictionary values may be lists for
|
|
#: representing multivalued query parameters.
|
|
self.params = from_key_val_list(params or [])
|
|
|
|
#: Dictionary of configuration parameters for this
|
|
#: :class:`Session <Session>`.
|
|
self.config = from_key_val_list(config or {})
|
|
|
|
#: Prefetch response content.
|
|
self.prefetch = prefetch
|
|
|
|
#: SSL Verification.
|
|
self.verify = verify
|
|
|
|
#: SSL certificate.
|
|
self.cert = cert
|
|
|
|
for (k, v) in list(defaults.items()):
|
|
self.config.setdefault(k, deepcopy(v))
|
|
|
|
# Set up a CookieJar to be used by default
|
|
if isinstance(cookies, cookielib.CookieJar):
|
|
self.cookies = cookies
|
|
else:
|
|
self.cookies = cookiejar_from_dict(cookies)
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, *args):
|
|
self.close()
|
|
|
|
def close(self):
|
|
pass
|
|
|
|
def request(self, method, url,
|
|
params=None,
|
|
data=None,
|
|
headers=None,
|
|
cookies=None,
|
|
files=None,
|
|
auth=None,
|
|
timeout=None,
|
|
allow_redirects=True,
|
|
proxies=None,
|
|
hooks=None,
|
|
return_response=True,
|
|
config=None,
|
|
prefetch=None,
|
|
verify=None,
|
|
cert=None):
|
|
|
|
req = Request()
|
|
req.method = method
|
|
req.url = url
|
|
req.headers = headers
|
|
req.files = files
|
|
req.data = data
|
|
req.params = params
|
|
req.auth = auth
|
|
req.cookies = cookies
|
|
# TODO: move to attached
|
|
req.allow_redirects = allow_redirects
|
|
req.proxies = proxies
|
|
req.hooks = hooks
|
|
|
|
prep = req.prepare()
|
|
|
|
# TODO: prepare cookies.
|
|
|
|
return self.send(prep)
|
|
|
|
|
|
def get(self, url, **kwargs):
|
|
"""Sends a GET request. Returns :class:`Response` object.
|
|
|
|
:param url: URL for the new :class:`Request` object.
|
|
:param \*\*kwargs: Optional arguments that ``request`` takes.
|
|
"""
|
|
|
|
kwargs.setdefault('allow_redirects', True)
|
|
return self.request('get', url, **kwargs)
|
|
|
|
def options(self, url, **kwargs):
|
|
"""Sends a OPTIONS request. Returns :class:`Response` object.
|
|
|
|
:param url: URL for the new :class:`Request` object.
|
|
:param \*\*kwargs: Optional arguments that ``request`` takes.
|
|
"""
|
|
|
|
kwargs.setdefault('allow_redirects', True)
|
|
return self.request('options', url, **kwargs)
|
|
|
|
def head(self, url, **kwargs):
|
|
"""Sends a HEAD request. Returns :class:`Response` object.
|
|
|
|
:param url: URL for the new :class:`Request` object.
|
|
:param \*\*kwargs: Optional arguments that ``request`` takes.
|
|
"""
|
|
|
|
kwargs.setdefault('allow_redirects', False)
|
|
return self.request('head', url, **kwargs)
|
|
|
|
def post(self, url, data=None, **kwargs):
|
|
"""Sends a POST request. Returns :class:`Response` object.
|
|
|
|
:param url: URL for the new :class:`Request` object.
|
|
:param data: (optional) Dictionary or bytes to send in the body of the :class:`Request`.
|
|
:param \*\*kwargs: Optional arguments that ``request`` takes.
|
|
"""
|
|
|
|
return self.request('post', url, data=data, **kwargs)
|
|
|
|
def put(self, url, data=None, **kwargs):
|
|
"""Sends a PUT request. Returns :class:`Response` object.
|
|
|
|
:param url: URL for the new :class:`Request` object.
|
|
:param data: (optional) Dictionary or bytes to send in the body of the :class:`Request`.
|
|
:param \*\*kwargs: Optional arguments that ``request`` takes.
|
|
"""
|
|
|
|
return self.request('put', url, data=data, **kwargs)
|
|
|
|
def patch(self, url, data=None, **kwargs):
|
|
"""Sends a PATCH request. Returns :class:`Response` object.
|
|
|
|
:param url: URL for the new :class:`Request` object.
|
|
:param data: (optional) Dictionary or bytes to send in the body of the :class:`Request`.
|
|
:param \*\*kwargs: Optional arguments that ``request`` takes.
|
|
"""
|
|
|
|
return self.request('patch', url, data=data, **kwargs)
|
|
|
|
def delete(self, url, **kwargs):
|
|
"""Sends a DELETE request. Returns :class:`Response` object.
|
|
|
|
:param url: URL for the new :class:`Request` object.
|
|
:param \*\*kwargs: Optional arguments that ``request`` takes.
|
|
"""
|
|
|
|
return self.request('delete', url, **kwargs)
|
|
|
|
def send(self, request):
|
|
"""Send a given PreparedRequest."""
|
|
adapter = HTTPAdapter()
|
|
r = adapter.send(request)
|
|
return r
|
|
|
|
def __getstate__(self):
|
|
return dict((attr, getattr(self, attr, None)) for attr in self.__attrs__)
|
|
|
|
def __setstate__(self, state):
|
|
for attr, value in state.items():
|
|
setattr(self, attr, value)
|
|
|
|
self.init_poolmanager()
|
|
|
|
|
|
def session(**kwargs):
|
|
"""Returns a :class:`Session` for context-management."""
|
|
|
|
return Session(**kwargs)
|