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')
46 logger.info('OUT {}'.format(result))
49 def store_auth(self, request, auth):
51 Store the auth object attached to this request's session
52 create that extension if needed
54 logger.info('IN {}'.format(auth))
55 return self._store(request, 'auth', auth)
57 def get_metadata(self, request):
59 retrieve metadata attached to this request's session, or None
61 return self._get(request, 'metadata')
63 def store_metadata(self, request, metadata):
65 Store the metadata object attached to this request's session
66 create that extension if needed
68 return self._store(request, 'metadata', metadata)
70 def _get(self, request, key):
71 "internal - retrieve key - do not create anything"
72 session = request.session
73 logger.debug("sessioncache._get_{} session={}".format(key, SessionCache._debug_session(session)))
74 # self._debug(request)
75 if cache_key not in session:
77 cached_uuid = session[cache_key]
78 if cached_uuid not in self:
80 extension = self[cached_uuid]
81 return getattr(extension, key)
83 def _store(self, request, key, value):
84 "internal - set key, attach and create extension if needed"
85 session = request.session
86 if cache_key not in session:
87 session[cache_key] = uuid.uuid1().int
88 cached_uuid = session[cache_key]
89 if cached_uuid not in self:
90 self[cached_uuid] = _SessionExtension()
91 extension = self[cached_uuid]
92 setattr(extension, key, value)
93 logger.debug("sessioncache._store_{} session={}".format(key, SessionCache._debug_session(session)))
94 # self._debug(request)
96 def end_session(self, request):
98 Clear all data related to this request's session has we are logging out
99 This is for garbage collection
101 session = request.session
102 logger.debug("SessionCache.end_session() {}".format(self._debug_session(session)))
103 if cache_key not in session:
105 cached_uuid = session[cache_key]
106 if cached_uuid in self:
107 del self[cached_uuid]
109 def _debug(self, request):
110 session = request.session
111 logger.debug("SessionCache: ---------- with session {}".format(self._debug_session(session)))
112 for k,v in self.iteritems():
113 logger.debug("SessionCache {} -> {}".format(k,v))
114 if cache_key not in session:
116 cached_uuid = session[cache_key]
117 if cached_uuid not in self:
119 extension = self[cached_uuid]
120 logger.debug("SessionCache: found extension {}".format(extension))
121 logger.debug("SessionCache: ----------")
124 def _debug_session(session):
126 result += "{} x {}".format(session, session.keys())
127 if cache_key in session:
128 result += " <{} = {}>".format(cache_key, session[cache_key])