module documentation

Store sessions in individual files within a directory. ### Note There was a problem with the existing code (adopted from the Python 2 version), which lead to an "EOFError: Ran out of input" exception The code in save_session() did: f = open(filename, 'wb') ...which immediately made the file zero bytes long. You can try this out in 2 terminals (where `s` is some dummy class with `s.id` as the file-name) with one doing: import pickle pickle.dump(s, f, 4) f.close() f = open(s.id, 'wb') If in the other terminal you do: f = open(s.id, 'rb') o = pickle.load(f) Traceback (most recent call last): ...EOFError: Ran out of input This is not entirely unexpected BUT the code in `load_session()`: f = open(filename, 'rb') fcntl.flock(f.fileno(), fcntl.LOCK_SH) ...could get the shared lock (LOCK_SH) after save_session() performed the open() but BEFORE `save_session()` got a chance to get the exclusive lock: f = open(filename, 'wb') fcntl.flock(f.fileno(), fcntl.LOCK_EX) (You can try it in the older code by quickly refreshing a browser calling a Quixote server.) What happened appears to have been: 1. save_session() opens the file to write [f = open(filename, 'wb')] 2. load_session() opens the file to read [f = open(filename, 'rb')] 3. load_session() asks for and GETS a shared lock [fcntl.LOCK_SH] 4. save_session() asks for an exclusive lock BUT gets blocked by the shared lock 5. load_session() tries to load the object and gets zero bytes. It then closes the file, mistakenly allowing save_session() to proceed. As save_session() truncated the file and then waited for an exclusive lock, we had to have load_session() check for a zero-sized file. If it has one, then save_session() has just created (or re-created) it and we should let go and try again. The originial code worked fine on hard discs but begain failing when SSDs came into use (due to speed, I suspect) ### Addendum It turns out that, during testing, one can get at `EOFError` from pickle anyway, so a check for that was added too.

Class DirectorySessionStore Store sessions in individual files within a directory. The noqa in the definitions are because 'id' is a Python keyword (blame Quixote, not me!)