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:19 -0700
committerSVN-Git Migration <python-modules-team@lists.alioth.debian.org>2015-10-08 13:41:19 -0700
commit1c0a691ebf468d42b7c0d6b0e9daf0b2ff82cc20 (patch)
treee228f79dfbc25cdacb33ce72b76732aec43d29ba /requests/sessions.py
parentbf12eaaa5428798962777e05fd98be024e0ce27c (diff)
downloadpython-requests-1c0a691ebf468d42b7c0d6b0e9daf0b2ff82cc20.tar
python-requests-1c0a691ebf468d42b7c0d6b0e9daf0b2ff82cc20.tar.gz
Imported Upstream version 0.8.2
Diffstat (limited to 'requests/sessions.py')
-rw-r--r--requests/sessions.py275
1 files changed, 235 insertions, 40 deletions
diff --git a/requests/sessions.py b/requests/sessions.py
index 50b09f6..247aa18 100644
--- a/requests/sessions.py
+++ b/requests/sessions.py
@@ -2,38 +2,92 @@
"""
requests.session
-~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~
This module provides a Session object to manage and persist settings across
requests (cookies, auth, proxies).
"""
-import cookielib
+from .defaults import defaults
+from .models import Request
+from .hooks import dispatch_hook
+from .utils import header_expand
+from .packages.urllib3.poolmanager import PoolManager
-from . import api
-from .utils import add_dict_to_cookiejar
+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, basestring):
+ 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
+
+ # 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']
+ __attrs__ = [
+ 'headers', 'cookies', 'auth', 'timeout', 'proxies', 'hooks',
+ 'params', 'config']
- def __init__(self, **kwargs):
+ def __init__(self,
+ headers=None,
+ cookies=None,
+ auth=None,
+ timeout=None,
+ proxies=None,
+ hooks=None,
+ params=None,
+ config=None):
- # Set up a CookieJar to be used by default
- self.cookies = cookielib.FileCookieJar()
+ self.headers = headers or {}
+ self.cookies = cookies or {}
+ self.auth = auth
+ self.timeout = timeout
+ self.proxies = proxies or {}
+ self.hooks = hooks or {}
+ self.params = params or {}
+ self.config = config or {}
- # Map args from kwargs to instance-local variables
- map(lambda k, v: (k in self.__attrs__) and setattr(self, k, v),
- kwargs.iterkeys(), kwargs.itervalues())
+ for (k, v) in defaults.items():
+ self.config.setdefault(k, v)
- # Map and wrap requests.api methods
- self._map_api_methods()
+ self.poolmanager = PoolManager(
+ num_pools=self.config.get('pool_connections'),
+ maxsize=self.config.get('pool_maxsize')
+ )
+
+ # Set up a CookieJar to be used by default
+ self.cookies = {}
+ # Add passed cookies in.
+ if cookies is not None:
+ self.cookies.update(cookies)
def __repr__(self):
return '<requests-client at 0x%x>' % (id(self))
@@ -42,43 +96,184 @@ class Session(object):
return self
def __exit__(self, *args):
- # print args
pass
+ def request(self, method, url,
+ params=None,
+ data=None,
+ headers=None,
+ cookies=None,
+ files=None,
+ auth=None,
+ timeout=None,
+ allow_redirects=False,
+ proxies=None,
+ hooks=None,
+ return_response=True,
+ config=None,
+ prefetch=False):
- def _map_api_methods(self):
- """Reads each available method from requests.api and decorates
- them with a wrapper, which inserts any instance-local attributes
- (from __attrs__) that have been set, combining them with **kwargs.
+ """Constructs and sends a :class:`Request <Request>`.
+ Returns :class:`Response <Response>` object.
+
+ :param method: method for the new :class:`Request` object.
+ :param url: URL for the new :class:`Request` object.
+ :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
+ :param data: (optional) Dictionary or bytes to send in the body of the :class:`Request`.
+ :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
+ :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
+ :param files: (optional) Dictionary of 'filename': file-like-objects for multipart encoding upload.
+ :param auth: (optional) Auth typle to enable Basic/Digest/Custom HTTP Auth.
+ :param timeout: (optional) Float describing the timeout of the request.
+ :param allow_redirects: (optional) Boolean. Set to True if POST/PUT/DELETE redirect following is allowed.
+ :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.
+ :param prefetch: (optional) if ``True``, the response content will be immediately downloaded.
"""
- def pass_args(func):
- def wrapper_func(*args, **kwargs):
- inst_attrs = dict((k, v) for k, v in self.__dict__.iteritems()
- if k in self.__attrs__)
- # Combine instance-local values with kwargs values, with
- # priority to values in kwargs
- kwargs = dict(inst_attrs.items() + kwargs.items())
+ method = str(method).upper()
+
+ # Default empty dicts for dict params.
+ cookies = {} if cookies is None else cookies
+ data = {} if data is None else data
+ files = {} if files is None else files
+ headers = {} if headers is None else headers
+ params = {} if params is None else params
+ hooks = {} if hooks is None else hooks
+ # use session's hooks as defaults
+ for key, cb in self.hooks.iteritems():
+ hooks.setdefault(key, cb)
+
+ # Expand header values.
+ if headers:
+ for k, v in headers.items() or {}:
+ headers[k] = header_expand(v)
+
+ args = dict(
+ method=method,
+ url=url,
+ data=data,
+ params=params,
+ headers=headers,
+ cookies=cookies,
+ files=files,
+ auth=auth,
+ hooks=hooks,
+ timeout=timeout,
+ allow_redirects=allow_redirects,
+ proxies=proxies,
+ config=config,
+ _poolmanager=self.poolmanager
+ )
+
+ # Merge local kwargs with session kwargs.
+ for attr in self.__attrs__:
+ session_val = getattr(self, attr, None)
+ local_val = args.get(attr)
+
+ args[attr] = merge_kwargs(local_val, session_val)
+
+ # Arguments manipulation hook.
+ args = dispatch_hook('args', args['hooks'], args)
+
+ # Create the (empty) response.
+ r = Request(**args)
+
+ # Give the response some context.
+ r.session = self
+
+ # Don't send if asked nicely.
+ if not return_response:
+ return r
+
+ # Send the HTTP Request.
+ r.send(prefetch=prefetch)
+
+ # Send any cookies back up the to the session.
+ self.cookies.update(r.response.cookies)
+
+ # Return the response.
+ return r.response
+
+
+ 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.
+ """
- # If a session request has a cookie_dict, inject the
- # values into the existing CookieJar instead.
- if isinstance(kwargs.get('cookies', None), dict):
- kwargs['cookies'] = add_dict_to_cookiejar(
- inst_attrs['cookies'], kwargs['cookies']
- )
+ kwargs.setdefault('allow_redirects', True)
+ return self.request('get', url, **kwargs)
- if kwargs.get('headers', None) and inst_attrs.get('headers', None):
- kwargs['headers'].update(inst_attrs['headers'])
- return func(*args, **kwargs)
- return wrapper_func
+ 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', True)
+ 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.
+ """
- # Map and decorate each function available in requests.api
- map(lambda fn: setattr(self, fn, pass_args(getattr(api, fn))),
- api.__all__)
+ return self.request('delete', url, **kwargs)
def session(**kwargs):
- """Returns a :class:`Session` for context-managment."""
+ """Returns a :class:`Session` for context-management."""
- return Session(**kwargs) \ No newline at end of file
+ return Session(**kwargs)