From 4c8af1fff47eea5f52c7b333101c221399c8c613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Wed, 15 May 2013 13:34:09 +0200 Subject: [PATCH] Fixes #1320: transport adapters stored in ordered form --- AUTHORS.rst | 1 + requests/sessions.py | 14 +++++++++----- test_requests.py | 40 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index d3198343..fce2cf9c 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -126,3 +126,4 @@ Patches and Suggestions - Bryce Boe @bboe - Colin Dunklau @cdunklau - Hugo Osvaldo Barrera @hobarrera +- Ɓukasz Langa @llanga diff --git a/requests/sessions.py b/requests/sessions.py index 185d5df7..77df0e82 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -11,14 +11,13 @@ requests (cookies, auth, proxies). import os from datetime import datetime -from .compat import cookielib +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 .exceptions import TooManyRedirects, InvalidSchema -from .compat import urlparse, urljoin from .adapters import HTTPAdapter from .utils import requote_uri, get_environ_proxies, get_netrc_auth @@ -223,9 +222,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 @@ -490,8 +489,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__) diff --git a/test_requests.py b/test_requests.py index da0adb1f..07a29554 100644 --- a/test_requests.py +++ b/test_requests.py @@ -11,6 +11,7 @@ import pickle import requests from requests.auth import HTTPDigestAuth +from requests.adapters import HTTPAdapter from requests.compat import str, cookielib from requests.cookies import cookiejar_from_dict from requests.structures import CaseInsensitiveDict @@ -482,6 +483,44 @@ class RequestsTestCase(unittest.TestCase): 'application/json' ) + def test_transport_adapter_ordering(self): + s = requests.Session() + order = ['https://', 'http://'] + self.assertEqual(order, list(s.adapters)) + s.mount('http://git', HTTPAdapter()) + s.mount('http://github', HTTPAdapter()) + s.mount('http://github.com', HTTPAdapter()) + s.mount('http://github.com/about/', HTTPAdapter()) + order = [ + 'http://github.com/about/', + 'http://github.com', + 'http://github', + 'http://git', + 'https://', + 'http://', + ] + self.assertEqual(order, list(s.adapters)) + s.mount('http://gittip', HTTPAdapter()) + s.mount('http://gittip.com', HTTPAdapter()) + s.mount('http://gittip.com/about/', HTTPAdapter()) + order = [ + 'http://github.com/about/', + 'http://gittip.com/about/', + 'http://github.com', + 'http://gittip.com', + 'http://github', + 'http://gittip', + 'http://git', + 'https://', + 'http://', + ] + self.assertEqual(order, list(s.adapters)) + s2 = requests.Session() + s2.adapters = {'http://': HTTPAdapter()} + s2.mount('https://', HTTPAdapter()) + self.assertTrue('http://' in s2.adapters) + self.assertTrue('https://' in s2.adapters) + class TestCaseInsensitiveDict(unittest.TestCase): @@ -627,6 +666,5 @@ class TestCaseInsensitiveDict(unittest.TestCase): self.assertEqual(frozenset(cid), keyset) - if __name__ == '__main__': unittest.main()