From 1722f289711e3d03b0e00fb548f3e8ea92544775 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Sun, 5 Aug 2012 23:28:19 -0400 Subject: [PATCH] Add to_key_val_lists to avoid repetition. It uses the same logic whenever we're trying to use a list of key values and avoid what I had started doing -- using the same pattern everywhere. proxies, and headers should both be covered by this commit. --- requests/models.py | 27 ++++----------------------- requests/sessions.py | 33 ++++++++++++++------------------- requests/utils.py | 27 +++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/requests/models.py b/requests/models.py index 514bcb4..cdcdee8 100644 --- a/requests/models.py +++ b/requests/models.py @@ -29,7 +29,7 @@ from .exceptions import ( from .utils import ( get_encoding_from_headers, stream_untransfer, guess_filename, requote_uri, stream_decode_response_unicode, get_netrc_auth, get_environ_proxies, - DEFAULT_CA_BUNDLE_PATH) + to_key_val_list, DEFAULT_CA_BUNDLE_PATH) from .compat import ( cookielib, urlparse, urlunparse, urljoin, urlsplit, urlencode, str, bytes, StringIO, is_py2, chardet, json, builtin_str) @@ -317,15 +317,8 @@ class Request(object): elif hasattr(data, 'read'): return data elif hasattr(data, '__iter__'): - try: - dict(data) - except ValueError: - raise ValueError('Unable to encode lists with elements that ' - 'are not 2-tuples.') - - params = list(data.items() if isinstance(data, dict) else data) result = [] - for k, vs in params: + for k, vs in to_key_val_list(data): for v in isinstance(vs, list) and vs or [vs]: result.append( (k.encode('utf-8') if isinstance(k, str) else k, @@ -339,20 +332,8 @@ class Request(object): if (not files) or isinstance(self.data, str): return None - try: - fields = list(self.data.items()) - except AttributeError: - dict(self.data) - fields = list(self.data) - - try: - dict(files) - except ValueError: - raise ValueError('Unable to encode lists with elements that ' - 'are not 2-tuples.') - - if isinstance(files, dict): - files = files.items() + fields = to_key_val_list(self.data) + files = to_key_val_list(files) for (k, v) in files: # support for explicit filename diff --git a/requests/sessions.py b/requests/sessions.py index ee47a01..32d39fc 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -15,7 +15,7 @@ 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 .utils import header_expand, to_key_val_list from .packages.urllib3.poolmanager import PoolManager @@ -38,14 +38,7 @@ def merge_kwargs(local_kwarg, default_kwarg): if not hasattr(default_kwarg, 'items'): return local_kwarg - try: - dict(local_kwarg) - except ValueError: - raise ValueError('Unable to encode lists with elements that are not ' - '2-tuples.') - - if hasattr(local_kwarg, 'items'): - local_kwarg = list(local_kwarg.items()) + local_kwarg = to_key_val_list(local_kwarg) # Update new values. kwargs = default_kwarg.copy() @@ -79,12 +72,12 @@ class Session(object): verify=True, cert=None): - self.headers = headers or {} + self.headers = to_key_val_list(headers or []) self.auth = auth self.timeout = timeout - self.proxies = proxies or {} + self.proxies = to_key_val_list(proxies or []) self.hooks = hooks or {} - self.params = params or {} + self.params = to_key_val_list(params or []) self.config = config or {} self.prefetch = prefetch self.verify = verify @@ -157,10 +150,10 @@ class Session(object): method = str(method).upper() # Default empty dicts for dict params. - 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 + 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 prefetch = self.prefetch or prefetch @@ -170,8 +163,10 @@ class Session(object): # Expand header values. if headers: - for k, v in list(headers.items()) or {}: - headers[k] = header_expand(v) + expanded = [] + for k, v in to_key_val_list(headers): + expanded.append((k, header_expand(v))) + headers = expanded args = dict( method=method, @@ -185,7 +180,7 @@ class Session(object): hooks=hooks, timeout=timeout, allow_redirects=allow_redirects, - proxies=proxies, + proxies=to_key_val_list(proxies), config=config, prefetch=prefetch, verify=verify, diff --git a/requests/utils.py b/requests/utils.py index ce08ba7..53bb80f 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -112,6 +112,33 @@ def guess_filename(obj): return name +def to_key_val_list(value): + """Take an object and test to see if it can be represented as a + dictionary. Unless it can not be represented as such, return a list of + tuples, e.g.,: + + >>> to_key_val_list([('key', 'val')]) + [('key', 'val')] + >>> to_key_val_list('string') + ValueError: ... + >>> to_key_val_list({'key': 'val'}) + [('key', 'val')] + """ + if value is None: + return None + + try: + dict(value) + except ValueError: + raise ValueError('Unable to encode lists with elements that are not ' + '2-tuples.') + + if isinstance(value, dict) or hasattr(value, 'items'): + value = value.items() + + return list(value) + + # From mitsuhiko/werkzeug (used with permission). def parse_list_header(value): """Parse lists as described by RFC 2068 Section 2. -- 2.7.4