From c8baf881257ff3194879ad79bef81c27007b4dcf Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Mon, 17 Nov 2014 22:13:35 -0600 Subject: [PATCH] Properly serialize RecentlyUsedContainers for cache RecentlyUsedContainers are threadsafe so they require a lock and as such cannot be serialized with pickle directly. To handle it, we need to convert it to a dictionary first and then back when deserializing. Fixes #2345 --- requests/sessions.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/requests/sessions.py b/requests/sessions.py index c2f42b1..ba8eaa3 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -36,6 +36,8 @@ from .status_codes import codes # formerly defined here, reexposed here for backward compatibility from .models import REDIRECT_STATI +REDIRECT_CACHE_SIZE = 1000 + def merge_setting(request_setting, session_setting, dict_class=OrderedDict): """ @@ -274,7 +276,7 @@ class Session(SessionRedirectMixin): __attrs__ = [ 'headers', 'cookies', 'auth', 'proxies', 'hooks', 'params', 'verify', 'cert', 'prefetch', 'adapters', 'stream', 'trust_env', - 'max_redirects', 'redirect_cache' + 'max_redirects', ] def __init__(self): @@ -329,7 +331,7 @@ class Session(SessionRedirectMixin): self.mount('http://', HTTPAdapter()) # Only store 1000 redirects to prevent using infinite memory - self.redirect_cache = RecentlyUsedContainer(1000) + self.redirect_cache = RecentlyUsedContainer(REDIRECT_CACHE_SIZE) def __enter__(self): return self @@ -660,12 +662,19 @@ class Session(SessionRedirectMixin): self.adapters[key] = self.adapters.pop(key) def __getstate__(self): - return dict((attr, getattr(self, attr, None)) for attr in self.__attrs__) + state = dict((attr, getattr(self, attr, None)) for attr in self.__attrs__) + state['redirect_cache'] = dict(self.redirect_cache) + return state def __setstate__(self, state): + redirect_cache = state.pop('redirect_cache', {}) for attr, value in state.items(): setattr(self, attr, value) + self.redirect_cache = RecentlyUsedContainer(REDIRECT_CACHE_SIZE) + for redirect, to in redirect_cache.items(): + self.redirect_cache[redirect] = to + def session(): """Returns a :class:`Session` for context-management.""" -- 2.34.1