3 from manifold.util.singleton import Singleton
5 from myslice.settings import logger
7 # the key attached to the session object, where we store
8 # the uuid attached to that session in this cache
9 cache_key = 'cached_uuid'
11 class _SessionExtension(object):
13 This object holds all the data we need to attach to a django session object
21 result = "<SessionExtension"
22 if self.metadata: result += " .metadata"
23 if self.auth: result += " .auth"
27 class SessionCache(dict):
29 As of django1.7, the session object as attached to a django request
30 gets JSON-serialized instead of pickled
31 This breaks our previous or passing data from request to request across
32 a given session - in particular for metadata and auth/session keys
33 Not that the problem is more with metadata as this is a class instance
34 and JSON cannot handle that
35 So instead we decorate the session object with a UID and retrieve all the rest
36 from the present - singleton - cache instance
39 __metaclass__ = Singleton
41 def get_auth(self, request):
43 Get the auth previously attached to the request's session, or None
45 result = self._get(request, 'auth')
48 def store_auth(self, request, auth):
50 Store the auth object attached to this request's session
51 create that extension if needed
53 return self._store(request, 'auth', auth)
55 def get_metadata(self, request):
57 retrieve metadata attached to this request's session, or None
59 return self._get(request, 'metadata')
61 def store_metadata(self, request, metadata):
63 Store the metadata object attached to this request's session
64 create that extension if needed
66 return self._store(request, 'metadata', metadata)
68 def _get(self, request, key):
69 "internal - retrieve key - do not create anything"
70 session = request.session
71 logger.debug("sessioncache._get_{} session={}".format(key, SessionCache._debug_session(session)))
72 # self._debug(request)
73 if cache_key not in session:
75 cached_uuid = session[cache_key]
76 if cached_uuid not in self:
78 extension = self[cached_uuid]
79 return getattr(extension, key)
81 def _store(self, request, key, value):
82 "internal - set key, attach and create extension if needed"
83 session = request.session
84 if cache_key not in session:
85 session[cache_key] = uuid.uuid1().int
86 cached_uuid = session[cache_key]
87 if cached_uuid not in self:
88 self[cached_uuid] = _SessionExtension()
89 extension = self[cached_uuid]
90 setattr(extension, key, value)
91 logger.debug("sessioncache._store_{} session={}".format(key, SessionCache._debug_session(session)))
92 # self._debug(request)
94 def end_session(self, request):
96 Clear all data related to this request's session has we are logging out
97 This is for garbage collection
99 session = request.session
100 logger.debug("SessionCache.end_session() {}".format(self._debug_session(session)))
101 if cache_key not in session:
103 cached_uuid = session[cache_key]
104 if cached_uuid in self:
105 del self[cached_uuid]
107 def _debug(self, request):
108 session = request.session
109 logger.debug("SessionCache: ---------- with session {}".format(self._debug_session(session)))
110 for k,v in self.iteritems():
111 logger.debug("SessionCache {} -> {}".format(k,v))
112 if cache_key not in session:
114 cached_uuid = session[cache_key]
115 if cached_uuid not in self:
117 extension = self[cached_uuid]
118 logger.debug("SessionCache: found extension {}".format(extension))
119 logger.debug("SessionCache: ----------")
122 def _debug_session(session):
124 result += "{} x {}".format(session, session.keys())
125 if cache_key in session:
126 result += " <{} = {}>".format(cache_key, session[cache_key])