Search code examples
pythoncherrypy

Initializing cherrypy.session early


I love CherryPy's API for sessions, except for one detail. Instead of saying cherrypy.session["spam"] I'd like to be able to just say session["spam"].

Unfortunately, I can't simply have a global from cherrypy import session in one of my modules, because the cherrypy.session object isn't created until the first time a page request is made. Is there some way to get CherryPy to initialize its session object immediately instead of on the first page request?

I have two ugly alternatives if the answer is no:

First, I can do something like this

def import_session():
    global session
    while not hasattr(cherrypy, "session"):
        sleep(0.1)
    session = cherrypy.session

Thread(target=import_session).start()

This feels like a big kludge, but I really hate writing cherrypy.session["spam"] every time, so to me it's worth it.

My second solution is to do something like

class SessionKludge:
    def __getitem__(self, name):
        return cherrypy.session[name]
    def __setitem__(self, name, val):
        cherrypy.session[name] = val

session = SessionKludge()

but this feels like an even bigger kludge and I'd need to do more work to implement the other dictionary functions such as .get

So I'd definitely prefer a simple way to initialize the object myself. Does anyone know how to do this?


Solution

  • For CherryPy 3.1, you would need to find the right subclass of Session, run its 'setup' classmethod, and then set cherrypy.session to a ThreadLocalProxy. That all happens in cherrypy.lib.sessions.init, in the following chunks:

    # Find the storage class and call setup (first time only).
    storage_class = storage_type.title() + 'Session'
    storage_class = globals()[storage_class]
    if not hasattr(cherrypy, "session"):
        if hasattr(storage_class, "setup"):
            storage_class.setup(**kwargs)
    
    # Create cherrypy.session which will proxy to cherrypy.serving.session
    if not hasattr(cherrypy, "session"):
        cherrypy.session = cherrypy._ThreadLocalProxy('session')
    

    Reducing (replace FileSession with the subclass you want):

    FileSession.setup(**kwargs)
    cherrypy.session = cherrypy._ThreadLocalProxy('session')
    

    The "kwargs" consist of "timeout", "clean_freq", and any subclass-specific entries from tools.sessions.* config.