try: from cPickle import dump, load except ImportError: from Pickle import dump, load import threading, os from LoginKit import UserManager, SimpleUser class PickleUserManager(UserManager): """ This user manager stores the user objects in pickled files. Give `path` to the constructor to indicate where these files should be kept. """ def __init__(self, path, userClass=None, **kw): """ `path` is the location where pickle files will be stored. `userClass` is the class for creating new users (default SimpleUser). """ UserManager.__init__(self, **kw) self._path = path if not os.path.exists(path): os.makedirs(path) self._lock = threading.Lock() self._userIDMap = self.loadUserIDMap() if userClass is None: userClass = SimpleUser self._userClass = userClass self._nextUserID = self.loadNextUserID() self._cache = {} def loadUserIDMap(self): return loadPickle(os.path.join(self._path, 'UserID-index.pickle'), default={}) def saveUserIDMap(self): savePickle(os.path.join(self._path, 'UserID-index.pickle'), self._userIDMap) def loadNextUserID(self): filename = os.path.join(self._path, 'UserID-nextID.txt') if not os.path.exists(filename): return 1 else: f = open(filename) val = int(f.read()) f.close() return val def saveNextUserID(self): f = open(os.path.join(self._path, 'UserID-nextID.txt'), 'w') f.write(str(self._nextUserID)) f.close() def nextUserID(self): self._lock.acquire() val = self._nextUserID self._nextUserID += 1 self.saveNextUserID() self._lock.release() return val def filenameForUserID(self, userID): return os.path.join(self._path, 'User-%i.pickle' % userID) def userForUserID(self, userID): user = self._cache.get(userID) if user is None: user = load(self.filenameForUserID(userID)) self._cache[userID] = user return user def userIDForUsername(self, username): return self._userIDMap.get(username) def usernameForUserID(self, userID): for username, possibleUserID in self._userIDMap.items(): if possibleUserID == userID: return username return None def newUser(self): user = self._userClass(self) user.setUserID(self.nextUserID()) return user def changeUsername(self, user, oldUsername): if self._userIDMap.has_key(user.username()): raise UserExistsError, "User %s already exists" % user.username() if oldUsername: del self._userIDMap[oldUsername] self._userIDMap[user.username()] = user.userID() self.saveUserIDMap() def userForUserID(self, userID): user = loadPickle(self.filenameForUserID(userID), default=None) if user: user._manager = self return user def saveUser(self, user): savePickle(self.filenameForUserID(user.userID()), user) def userChanged(self, user): self.saveUser(user) def allUserIDs(self): return self._userIDMap.values() def userClass(self): return self._userClass def deleteUser(self, user): del self._userIDMap[user.username()] self.saveUserIDMap() os.unlink(self.filenameForUserID(user.userID())) ############################################################ ## Utility functions ############################################################ class NoDefault: pass def loadPickle(filename, default=NoDefault): if os.path.exists(filename): f = open(filename, 'rb') value = load(f) f.close() return value else: if default is NoDefault: raise IOError, 'file %r does not exists' % filename return default def savePickle(filename, value): f = open(filename, 'wb') dump(value, f) f.close()