| OLD | NEW | 
|---|
| 1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- | 
| 2 | 2 | 
| 3 """ | 3 """ | 
| 4 requests.session | 4 requests.session | 
| 5 ~~~~~~~~~~~~~~~~ | 5 ~~~~~~~~~~~~~~~~ | 
| 6 | 6 | 
| 7 This module provides a Session object to manage and persist settings across | 7 This module provides a Session object to manage and persist settings across | 
| 8 requests (cookies, auth, proxies). | 8 requests (cookies, auth, proxies). | 
| 9 | 9 | 
| 10 """ | 10 """ | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 64 | 64 | 
| 65     return merged_setting | 65     return merged_setting | 
| 66 | 66 | 
| 67 | 67 | 
| 68 class SessionRedirectMixin(object): | 68 class SessionRedirectMixin(object): | 
| 69     def resolve_redirects(self, resp, req, stream=False, timeout=None, | 69     def resolve_redirects(self, resp, req, stream=False, timeout=None, | 
| 70                           verify=True, cert=None, proxies=None): | 70                           verify=True, cert=None, proxies=None): | 
| 71         """Receives a Response. Returns a generator of Responses.""" | 71         """Receives a Response. Returns a generator of Responses.""" | 
| 72 | 72 | 
| 73         i = 0 | 73         i = 0 | 
| 74         prepared_request = PreparedRequest() |  | 
| 75         prepared_request.body = req.body |  | 
| 76         prepared_request.headers = req.headers.copy() |  | 
| 77         prepared_request.hooks = req.hooks |  | 
| 78         prepared_request.method = req.method |  | 
| 79         prepared_request.url = req.url |  | 
| 80 | 74 | 
| 81         # ((resp.status_code is codes.see_other)) | 75         # ((resp.status_code is codes.see_other)) | 
| 82         while (('location' in resp.headers and resp.status_code in REDIRECT_STAT
     I)): | 76         while (('location' in resp.headers and resp.status_code in REDIRECT_STAT
     I)): | 
|  | 77             prepared_request = req.copy() | 
| 83 | 78 | 
| 84             resp.content  # Consume socket so it can be released | 79             resp.content  # Consume socket so it can be released | 
| 85 | 80 | 
| 86             if i >= self.max_redirects: | 81             if i >= self.max_redirects: | 
| 87                 raise TooManyRedirects('Exceeded %s redirects.' % self.max_redir
     ects) | 82                 raise TooManyRedirects('Exceeded %s redirects.' % self.max_redir
     ects) | 
| 88 | 83 | 
| 89             # Release the connection back into the pool. | 84             # Release the connection back into the pool. | 
| 90             resp.close() | 85             resp.close() | 
| 91 | 86 | 
| 92             url = resp.headers['location'] | 87             url = resp.headers['location'] | 
| 93             method = prepared_request.method | 88             method = req.method | 
| 94 | 89 | 
| 95             # Handle redirection without scheme (see: RFC 1808 Section 4) | 90             # Handle redirection without scheme (see: RFC 1808 Section 4) | 
| 96             if url.startswith('//'): | 91             if url.startswith('//'): | 
| 97                 parsed_rurl = urlparse(resp.url) | 92                 parsed_rurl = urlparse(resp.url) | 
| 98                 url = '%s:%s' % (parsed_rurl.scheme, url) | 93                 url = '%s:%s' % (parsed_rurl.scheme, url) | 
| 99 | 94 | 
|  | 95             # The scheme should be lower case... | 
|  | 96             if '://' in url: | 
|  | 97                 scheme, uri = url.split('://', 1) | 
|  | 98                 url = '%s://%s' % (scheme.lower(), uri) | 
|  | 99 | 
| 100             # Facilitate non-RFC2616-compliant 'location' headers | 100             # Facilitate non-RFC2616-compliant 'location' headers | 
| 101             # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/re
     source') | 101             # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/re
     source') | 
| 102             # Compliant with RFC3986, we percent encode the url. | 102             # Compliant with RFC3986, we percent encode the url. | 
| 103             if not urlparse(url).netloc: | 103             if not urlparse(url).netloc: | 
| 104                 url = urljoin(resp.url, requote_uri(url)) | 104                 url = urljoin(resp.url, requote_uri(url)) | 
| 105             else: | 105             else: | 
| 106                 url = requote_uri(url) | 106                 url = requote_uri(url) | 
| 107 | 107 | 
| 108             prepared_request.url = url | 108             prepared_request.url = url | 
| 109 | 109 | 
| 110             # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4 | 110             # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4 | 
| 111             if (resp.status_code == codes.see_other and | 111             if (resp.status_code == codes.see_other and | 
| 112                     prepared_request.method != 'HEAD'): | 112                     method != 'HEAD'): | 
| 113                 method = 'GET' | 113                 method = 'GET' | 
| 114 | 114 | 
| 115             # Do what the browsers do, despite standards... | 115             # Do what the browsers do, despite standards... | 
| 116             if (resp.status_code in (codes.moved, codes.found) and | 116             if (resp.status_code in (codes.moved, codes.found) and | 
| 117                     prepared_request.method not in ('GET', 'HEAD')): | 117                     method not in ('GET', 'HEAD')): | 
| 118                 method = 'GET' | 118                 method = 'GET' | 
| 119 | 119 | 
| 120             prepared_request.method = method | 120             prepared_request.method = method | 
| 121 | 121 | 
| 122             # https://github.com/kennethreitz/requests/issues/1084 | 122             # https://github.com/kennethreitz/requests/issues/1084 | 
| 123             if resp.status_code not in (codes.temporary, codes.resume): | 123             if resp.status_code not in (codes.temporary, codes.resume): | 
| 124                 if 'Content-Length' in prepared_request.headers: | 124                 if 'Content-Length' in prepared_request.headers: | 
| 125                     del prepared_request.headers['Content-Length'] | 125                     del prepared_request.headers['Content-Length'] | 
| 126 | 126 | 
| 127                 prepared_request.body = None | 127                 prepared_request.body = None | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 146 | 146 | 
| 147             extract_cookies_to_jar(self.cookies, prepared_request, resp.raw) | 147             extract_cookies_to_jar(self.cookies, prepared_request, resp.raw) | 
| 148 | 148 | 
| 149             i += 1 | 149             i += 1 | 
| 150             yield resp | 150             yield resp | 
| 151 | 151 | 
| 152 | 152 | 
| 153 class Session(SessionRedirectMixin): | 153 class Session(SessionRedirectMixin): | 
| 154     """A Requests session. | 154     """A Requests session. | 
| 155 | 155 | 
| 156     Provides cookie persistience, connection-pooling, and configuration. | 156     Provides cookie persistence, connection-pooling, and configuration. | 
| 157 | 157 | 
| 158     Basic Usage:: | 158     Basic Usage:: | 
| 159 | 159 | 
| 160       >>> import requests | 160       >>> import requests | 
| 161       >>> s = requests.Session() | 161       >>> s = requests.Session() | 
| 162       >>> s.get('http://httpbin.org/get') | 162       >>> s.get('http://httpbin.org/get') | 
| 163       200 | 163       200 | 
| 164     """ | 164     """ | 
| 165 | 165 | 
| 166     __attrs__ = [ | 166     __attrs__ = [ | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 201         #: SSL certificate default. | 201         #: SSL certificate default. | 
| 202         self.cert = None | 202         self.cert = None | 
| 203 | 203 | 
| 204         #: Maximum number of redirects allowed. If the request exceeds this | 204         #: Maximum number of redirects allowed. If the request exceeds this | 
| 205         #: limit, a :class:`TooManyRedirects` exception is raised. | 205         #: limit, a :class:`TooManyRedirects` exception is raised. | 
| 206         self.max_redirects = DEFAULT_REDIRECT_LIMIT | 206         self.max_redirects = DEFAULT_REDIRECT_LIMIT | 
| 207 | 207 | 
| 208         #: Should we trust the environment? | 208         #: Should we trust the environment? | 
| 209         self.trust_env = True | 209         self.trust_env = True | 
| 210 | 210 | 
| 211         # Set up a CookieJar to be used by default | 211         #: A CookieJar containing all currently outstanding cookies set on this | 
|  | 212         #: session. By default it is a | 
|  | 213         #: :class:`RequestsCookieJar <requests.cookies.RequestsCookieJar>`, but | 
|  | 214         #: may be any other ``cookielib.CookieJar`` compatible object. | 
| 212         self.cookies = cookiejar_from_dict({}) | 215         self.cookies = cookiejar_from_dict({}) | 
| 213 | 216 | 
| 214         # Default connection adapters. | 217         # Default connection adapters. | 
| 215         self.adapters = OrderedDict() | 218         self.adapters = OrderedDict() | 
| 216         self.mount('https://', HTTPAdapter()) | 219         self.mount('https://', HTTPAdapter()) | 
| 217         self.mount('http://', HTTPAdapter()) | 220         self.mount('http://', HTTPAdapter()) | 
| 218 | 221 | 
| 219     def __enter__(self): | 222     def __enter__(self): | 
| 220         return self | 223         return self | 
| 221 | 224 | 
| 222     def __exit__(self, *args): | 225     def __exit__(self, *args): | 
| 223         self.close() | 226         self.close() | 
| 224 | 227 | 
|  | 228     def prepare_request(self, request): | 
|  | 229         """Constructs a :class:`PreparedRequest <PreparedRequest>` for | 
|  | 230         transmission and returns it. The :class:`PreparedRequest` has settings | 
|  | 231         merged from the :class:`Request <Request>` instance and those of the | 
|  | 232         :class:`Session`. | 
|  | 233 | 
|  | 234         :param request: :class:`Request` instance to prepare with this | 
|  | 235         session's settings. | 
|  | 236         """ | 
|  | 237         cookies = request.cookies or {} | 
|  | 238 | 
|  | 239         # Bootstrap CookieJar. | 
|  | 240         if not isinstance(cookies, cookielib.CookieJar): | 
|  | 241             cookies = cookiejar_from_dict(cookies) | 
|  | 242 | 
|  | 243         # Merge with session cookies | 
|  | 244         merged_cookies = RequestsCookieJar() | 
|  | 245         merged_cookies.update(self.cookies) | 
|  | 246         merged_cookies.update(cookies) | 
|  | 247 | 
|  | 248 | 
|  | 249         # Set environment's basic authentication if not explicitly set. | 
|  | 250         auth = request.auth | 
|  | 251         if self.trust_env and not auth and not self.auth: | 
|  | 252             auth = get_netrc_auth(request.url) | 
|  | 253 | 
|  | 254         p = PreparedRequest() | 
|  | 255         p.prepare( | 
|  | 256             method=request.method.upper(), | 
|  | 257             url=request.url, | 
|  | 258             files=request.files, | 
|  | 259             data=request.data, | 
|  | 260             headers=merge_setting(request.headers, self.headers, dict_class=Case
     InsensitiveDict), | 
|  | 261             params=merge_setting(request.params, self.params), | 
|  | 262             auth=merge_setting(auth, self.auth), | 
|  | 263             cookies=merged_cookies, | 
|  | 264             hooks=merge_setting(request.hooks, self.hooks), | 
|  | 265         ) | 
|  | 266         return p | 
|  | 267 | 
| 225     def request(self, method, url, | 268     def request(self, method, url, | 
| 226         params=None, | 269         params=None, | 
| 227         data=None, | 270         data=None, | 
| 228         headers=None, | 271         headers=None, | 
| 229         cookies=None, | 272         cookies=None, | 
| 230         files=None, | 273         files=None, | 
| 231         auth=None, | 274         auth=None, | 
| 232         timeout=None, | 275         timeout=None, | 
| 233         allow_redirects=True, | 276         allow_redirects=True, | 
| 234         proxies=None, | 277         proxies=None, | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 258         :param allow_redirects: (optional) Boolean. Set to True by default. | 301         :param allow_redirects: (optional) Boolean. Set to True by default. | 
| 259         :param proxies: (optional) Dictionary mapping protocol to the URL of | 302         :param proxies: (optional) Dictionary mapping protocol to the URL of | 
| 260             the proxy. | 303             the proxy. | 
| 261         :param stream: (optional) whether to immediately download the response | 304         :param stream: (optional) whether to immediately download the response | 
| 262             content. Defaults to ``False``. | 305             content. Defaults to ``False``. | 
| 263         :param verify: (optional) if ``True``, the SSL cert will be verified. | 306         :param verify: (optional) if ``True``, the SSL cert will be verified. | 
| 264             A CA_BUNDLE path can also be provided. | 307             A CA_BUNDLE path can also be provided. | 
| 265         :param cert: (optional) if String, path to ssl client cert file (.pem). | 308         :param cert: (optional) if String, path to ssl client cert file (.pem). | 
| 266             If Tuple, ('cert', 'key') pair. | 309             If Tuple, ('cert', 'key') pair. | 
| 267         """ | 310         """ | 
|  | 311         # Create the Request. | 
|  | 312         req = Request( | 
|  | 313             method = method.upper(), | 
|  | 314             url = url, | 
|  | 315             headers = headers, | 
|  | 316             files = files, | 
|  | 317             data = data or {}, | 
|  | 318             params = params or {}, | 
|  | 319             auth = auth, | 
|  | 320             cookies = cookies, | 
|  | 321             hooks = hooks, | 
|  | 322         ) | 
|  | 323         prep = self.prepare_request(req) | 
| 268 | 324 | 
| 269         cookies = cookies or {} |  | 
| 270         proxies = proxies or {} | 325         proxies = proxies or {} | 
| 271 | 326 | 
| 272         # Bootstrap CookieJar. |  | 
| 273         if not isinstance(cookies, cookielib.CookieJar): |  | 
| 274             cookies = cookiejar_from_dict(cookies) |  | 
| 275 |  | 
| 276         # Merge with session cookies |  | 
| 277         merged_cookies = RequestsCookieJar() |  | 
| 278         merged_cookies.update(self.cookies) |  | 
| 279         merged_cookies.update(cookies) |  | 
| 280         cookies = merged_cookies |  | 
| 281 |  | 
| 282         # Gather clues from the surrounding environment. | 327         # Gather clues from the surrounding environment. | 
| 283         if self.trust_env: | 328         if self.trust_env: | 
| 284             # Set environment's proxies. | 329             # Set environment's proxies. | 
| 285             env_proxies = get_environ_proxies(url) or {} | 330             env_proxies = get_environ_proxies(url) or {} | 
| 286             for (k, v) in env_proxies.items(): | 331             for (k, v) in env_proxies.items(): | 
| 287                 proxies.setdefault(k, v) | 332                 proxies.setdefault(k, v) | 
| 288 | 333 | 
| 289             # Set environment's basic authentication. |  | 
| 290             if not auth: |  | 
| 291                 auth = get_netrc_auth(url) |  | 
| 292 |  | 
| 293             # Look for configuration. | 334             # Look for configuration. | 
| 294             if not verify and verify is not False: | 335             if not verify and verify is not False: | 
| 295                 verify = os.environ.get('REQUESTS_CA_BUNDLE') | 336                 verify = os.environ.get('REQUESTS_CA_BUNDLE') | 
| 296 | 337 | 
| 297             # Curl compatibility. | 338             # Curl compatibility. | 
| 298             if not verify and verify is not False: | 339             if not verify and verify is not False: | 
| 299                 verify = os.environ.get('CURL_CA_BUNDLE') | 340                 verify = os.environ.get('CURL_CA_BUNDLE') | 
| 300 | 341 | 
| 301         # Merge all the kwargs. | 342         # Merge all the kwargs. | 
| 302         params = merge_setting(params, self.params) |  | 
| 303         headers = merge_setting(headers, self.headers, dict_class=CaseInsensitiv
     eDict) |  | 
| 304         auth = merge_setting(auth, self.auth) |  | 
| 305         proxies = merge_setting(proxies, self.proxies) | 343         proxies = merge_setting(proxies, self.proxies) | 
| 306         hooks = merge_setting(hooks, self.hooks) |  | 
| 307         stream = merge_setting(stream, self.stream) | 344         stream = merge_setting(stream, self.stream) | 
| 308         verify = merge_setting(verify, self.verify) | 345         verify = merge_setting(verify, self.verify) | 
| 309         cert = merge_setting(cert, self.cert) | 346         cert = merge_setting(cert, self.cert) | 
| 310 | 347 | 
| 311         # Create the Request. |  | 
| 312         req = Request() |  | 
| 313         req.method = method.upper() |  | 
| 314         req.url = url |  | 
| 315         req.headers = headers |  | 
| 316         req.files = files |  | 
| 317         req.data = data |  | 
| 318         req.params = params |  | 
| 319         req.auth = auth |  | 
| 320         req.cookies = cookies |  | 
| 321         req.hooks = hooks |  | 
| 322 |  | 
| 323         # Prepare the Request. |  | 
| 324         prep = req.prepare() |  | 
| 325 |  | 
| 326         # Send the request. | 348         # Send the request. | 
| 327         send_kwargs = { | 349         send_kwargs = { | 
| 328             'stream': stream, | 350             'stream': stream, | 
| 329             'timeout': timeout, | 351             'timeout': timeout, | 
| 330             'verify': verify, | 352             'verify': verify, | 
| 331             'cert': cert, | 353             'cert': cert, | 
| 332             'proxies': proxies, | 354             'proxies': proxies, | 
| 333             'allow_redirects': allow_redirects, | 355             'allow_redirects': allow_redirects, | 
| 334         } | 356         } | 
| 335         resp = self.send(prep, **send_kwargs) | 357         resp = self.send(prep, **send_kwargs) | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 409         """Send a given PreparedRequest.""" | 431         """Send a given PreparedRequest.""" | 
| 410         # Set defaults that the hooks can utilize to ensure they always have | 432         # Set defaults that the hooks can utilize to ensure they always have | 
| 411         # the correct parameters to reproduce the previous request. | 433         # the correct parameters to reproduce the previous request. | 
| 412         kwargs.setdefault('stream', self.stream) | 434         kwargs.setdefault('stream', self.stream) | 
| 413         kwargs.setdefault('verify', self.verify) | 435         kwargs.setdefault('verify', self.verify) | 
| 414         kwargs.setdefault('cert', self.cert) | 436         kwargs.setdefault('cert', self.cert) | 
| 415         kwargs.setdefault('proxies', self.proxies) | 437         kwargs.setdefault('proxies', self.proxies) | 
| 416 | 438 | 
| 417         # It's possible that users might accidentally send a Request object. | 439         # It's possible that users might accidentally send a Request object. | 
| 418         # Guard against that specific failure case. | 440         # Guard against that specific failure case. | 
| 419         if getattr(request, 'prepare', None): | 441         if not isinstance(request, PreparedRequest): | 
| 420             raise ValueError('You can only send PreparedRequests.') | 442             raise ValueError('You can only send PreparedRequests.') | 
| 421 | 443 | 
| 422         # Set up variables needed for resolve_redirects and dispatching of | 444         # Set up variables needed for resolve_redirects and dispatching of | 
| 423         # hooks | 445         # hooks | 
| 424         allow_redirects = kwargs.pop('allow_redirects', True) | 446         allow_redirects = kwargs.pop('allow_redirects', True) | 
| 425         stream = kwargs.get('stream') | 447         stream = kwargs.get('stream') | 
| 426         timeout = kwargs.get('timeout') | 448         timeout = kwargs.get('timeout') | 
| 427         verify = kwargs.get('verify') | 449         verify = kwargs.get('verify') | 
| 428         cert = kwargs.get('cert') | 450         cert = kwargs.get('cert') | 
| 429         proxies = kwargs.get('proxies') | 451         proxies = kwargs.get('proxies') | 
| 430         hooks = request.hooks | 452         hooks = request.hooks | 
| 431 | 453 | 
| 432         # Get the appropriate adapter to use | 454         # Get the appropriate adapter to use | 
| 433         adapter = self.get_adapter(url=request.url) | 455         adapter = self.get_adapter(url=request.url) | 
| 434 | 456 | 
| 435         # Start time (approximately) of the request | 457         # Start time (approximately) of the request | 
| 436         start = datetime.utcnow() | 458         start = datetime.utcnow() | 
| 437         # Send the request | 459         # Send the request | 
| 438         r = adapter.send(request, **kwargs) | 460         r = adapter.send(request, **kwargs) | 
| 439         # Total elapsed time of the request (approximately) | 461         # Total elapsed time of the request (approximately) | 
| 440         r.elapsed = datetime.utcnow() - start | 462         r.elapsed = datetime.utcnow() - start | 
| 441 | 463 | 
| 442         # Response manipulation hooks | 464         # Response manipulation hooks | 
| 443         r = dispatch_hook('response', hooks, r, **kwargs) | 465         r = dispatch_hook('response', hooks, r, **kwargs) | 
| 444 | 466 | 
| 445         # Persist cookies | 467         # Persist cookies | 
|  | 468         if r.history: | 
|  | 469             # If the hooks create history then we want those cookies too | 
|  | 470             for resp in r.history: | 
|  | 471                 extract_cookies_to_jar(self.cookies, resp.request, resp.raw) | 
| 446         extract_cookies_to_jar(self.cookies, request, r.raw) | 472         extract_cookies_to_jar(self.cookies, request, r.raw) | 
| 447 | 473 | 
| 448         # Redirect resolving generator. | 474         # Redirect resolving generator. | 
| 449         gen = self.resolve_redirects(r, request, stream=stream, | 475         gen = self.resolve_redirects(r, request, stream=stream, | 
| 450                                      timeout=timeout, verify=verify, cert=cert, | 476                                      timeout=timeout, verify=verify, cert=cert, | 
| 451                                      proxies=proxies) | 477                                      proxies=proxies) | 
| 452 | 478 | 
| 453         # Resolve redirects if allowed. | 479         # Resolve redirects if allowed. | 
| 454         history = [resp for resp in gen] if allow_redirects else [] | 480         history = [resp for resp in gen] if allow_redirects else [] | 
| 455 | 481 | 
| 456         # Shuffle things around if there's history. | 482         # Shuffle things around if there's history. | 
| 457         if history: | 483         if history: | 
| 458             # Insert the first (original) request at the start | 484             # Insert the first (original) request at the start | 
| 459             history.insert(0, r) | 485             history.insert(0, r) | 
| 460             # Get the last request made | 486             # Get the last request made | 
| 461             r = history.pop() | 487             r = history.pop() | 
| 462             r.history = tuple(history) | 488             r.history = tuple(history) | 
| 463 | 489 | 
| 464         return r | 490         return r | 
| 465 | 491 | 
| 466     def get_adapter(self, url): | 492     def get_adapter(self, url): | 
| 467         """Returns the appropriate connnection adapter for the given URL.""" | 493         """Returns the appropriate connnection adapter for the given URL.""" | 
| 468         for (prefix, adapter) in self.adapters.items(): | 494         for (prefix, adapter) in self.adapters.items(): | 
| 469 | 495 | 
| 470             if url.startswith(prefix): | 496             if url.lower().startswith(prefix): | 
| 471                 return adapter | 497                 return adapter | 
| 472 | 498 | 
| 473         # Nothing matches :-/ | 499         # Nothing matches :-/ | 
| 474         raise InvalidSchema("No connection adapters were found for '%s'" % url) | 500         raise InvalidSchema("No connection adapters were found for '%s'" % url) | 
| 475 | 501 | 
| 476     def close(self): | 502     def close(self): | 
| 477         """Closes all adapters and as such the session""" | 503         """Closes all adapters and as such the session""" | 
| 478         for _, v in self.adapters.items(): | 504         for v in self.adapters.values(): | 
| 479             v.close() | 505             v.close() | 
| 480 | 506 | 
| 481     def mount(self, prefix, adapter): | 507     def mount(self, prefix, adapter): | 
| 482         """Registers a connection adapter to a prefix. | 508         """Registers a connection adapter to a prefix. | 
| 483 | 509 | 
| 484         Adapters are sorted in descending order by key length.""" | 510         Adapters are sorted in descending order by key length.""" | 
| 485         self.adapters[prefix] = adapter | 511         self.adapters[prefix] = adapter | 
| 486         keys_to_move = [k for k in self.adapters if len(k) < len(prefix)] | 512         keys_to_move = [k for k in self.adapters if len(k) < len(prefix)] | 
| 487         for key in keys_to_move: | 513         for key in keys_to_move: | 
| 488             self.adapters[key] = self.adapters.pop(key) | 514             self.adapters[key] = self.adapters.pop(key) | 
| 489 | 515 | 
| 490     def __getstate__(self): | 516     def __getstate__(self): | 
| 491         return dict((attr, getattr(self, attr, None)) for attr in self.__attrs__
     ) | 517         return dict((attr, getattr(self, attr, None)) for attr in self.__attrs__
     ) | 
| 492 | 518 | 
| 493     def __setstate__(self, state): | 519     def __setstate__(self, state): | 
| 494         for attr, value in state.items(): | 520         for attr, value in state.items(): | 
| 495             setattr(self, attr, value) | 521             setattr(self, attr, value) | 
| 496 | 522 | 
| 497 | 523 | 
| 498 def session(): | 524 def session(): | 
| 499     """Returns a :class:`Session` for context-management.""" | 525     """Returns a :class:`Session` for context-management.""" | 
| 500 | 526 | 
| 501     return Session() | 527     return Session() | 
| OLD | NEW | 
|---|