From c997192277337d2c04497e4248d95f858636333f Mon Sep 17 00:00:00 2001 From: mdipierro Date: Tue, 27 Aug 2013 16:12:23 -0500 Subject: [PATCH] another possible solution to issue 1524, without monkey patching --- VERSION | 2 +- gluon/globals.py | 24 ++++++++++++++++++++---- gluon/monkey_patch_pickle.py | 9 --------- 3 files changed, 21 insertions(+), 14 deletions(-) delete mode 100644 gluon/monkey_patch_pickle.py diff --git a/VERSION b/VERSION index 35e184c6..9eabb450 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.6.0-development+timestamp.2013.08.27.15.54.04 +Version 2.6.0-development+timestamp.2013.08.27.16.11.32 diff --git a/gluon/globals.py b/gluon/globals.py index 1adf63b1..8537bfc6 100644 --- a/gluon/globals.py +++ b/gluon/globals.py @@ -23,13 +23,13 @@ from http import HTTP, redirect from fileutils import up from serializers import json, custom_json import settings -import monkey_patch_pickle from utils import web2py_uuid, secure_dumps, secure_loads from settings import global_settings import hashlib import portalocker import cPickle -import pickle +from pickle import Pickler, MARK, DICT, EMPTY_DICT +from types import DictionaryType import cStringIO import datetime import re @@ -54,7 +54,6 @@ try: except ImportError: have_minify = False - try: import simplejson as sj #external installed library except: @@ -77,6 +76,23 @@ less_template = '' css_inline = '' js_inline = '' +# IMPORTANT: +# this is required so that pickled dict(s) and class.__dict__ +# are sorted and web2py can detect without ambiguity when a session changes +class SortingPickler(Pickler): + def save_dict(self, obj): + self.write(EMPTY_DICT if self.bin else MARK+DICT) + self.memoize(obj) + self._batch_setitems([(key,obj[key]) for key in sorted(obj)]) + +SortingPickler.dispatch = copy.copy(Pickler.dispatch) +SortingPickler.dispatch[DictionaryType] = SortingPickler.save_dict + +def sorting_dumps(obj, protocol=None): + file = cStringIO.StringIO() + SortingPickler(file, protocol).dump(obj) + return file.getvalue() +# END ##################################################################### def copystream_progress(request, chunk_size=10 ** 5): """ @@ -979,7 +995,7 @@ class Session(Storage): if not previous_session_hash and not \ any(value is not None for value in self.itervalues()): return True - session_pickled = pickle.dumps(dict(self)) # requires monkey patched pickle + session_pickled = sorting_dumps(dict(self)) session_hash = hashlib.md5(session_pickled).hexdigest() if previous_session_hash == session_hash: return True diff --git a/gluon/monkey_patch_pickle.py b/gluon/monkey_patch_pickle.py deleted file mode 100644 index ff186523..00000000 --- a/gluon/monkey_patch_pickle.py +++ /dev/null @@ -1,9 +0,0 @@ -from pickle import Pickler, MARK, DICT, EMPTY_DICT -from types import DictionaryType - -def save_dict(self, obj): - self.write(EMPTY_DICT if self.bin else MARK+DICT) - self.memoize(obj) - self._batch_setitems([(key,obj[key]) for key in sorted(obj)]) - -Pickler.dispatch[DictionaryType] = save_dict