PK–žC8“×2EGG-INFO/zip-safe PK•žC8?ôD°±±EGG-INFO/SOURCES.txtREADME setup.cfg setup.py lib/MyghtyUtils.egg-info/PKG-INFO lib/MyghtyUtils.egg-info/SOURCES.txt lib/MyghtyUtils.egg-info/dependency_links.txt lib/MyghtyUtils.egg-info/top_level.txt lib/myghtyutils/__init__.py lib/myghtyutils/buffer.py lib/myghtyutils/container.py lib/myghtyutils/session.py lib/myghtyutils/synchronization.py lib/myghtyutils/util.py lib/myghtyutils/ext/__init__.py lib/myghtyutils/ext/memcached.py test/testbase.py PK•žC8“×2EGG-INFO/dependency_links.txt PK•žC8\Ì`EGG-INFO/PKG-INFOMetadata-Version: 1.0 Name: MyghtyUtils Version: 0.52 Summary: Container and Utility Functions from the Myghty Template Framework Home-page: http://www.myghty.org Author: Mike Bayer Author-email: mike@myghty.org License: MIT License Description: This is the set of utility classes used by Myghty templating. Included are: container - the Containment system providing back-end neutral key/value storage, with support for in-memory, DBM files, flat files, and memcached buffer - some functions for augmenting file objects util - various utility functions and objects synchronizer - provides many reader/single writer synchronization using either thread mutexes or lockfiles session - provides a Session interface built upon the Container, similar interface to mod_python session. Currently needs a mod_python-like request object, this should be changed to something more generic. `Development SVN `_ Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python PK•žC8Cb´y EGG-INFO/top_level.txtmyghtyutils PK—tö4Lµ!B/B/myghtyutils/synchronization.py# $Id: synchronization.py,v 1.1.1.1 2006/01/12 20:54:38 classic Exp $ # synchronization.py - synchronization functions for Myghty # Copyright (C) 2004, 2005 Michael Bayer mike_mp@zzzcomputing.com # # This module is part of Myghty and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php # __all__ = ["Synchronizer", "NameLock", "_threading", "_thread"] import os, weakref, tempfile, re, sys from util import * try: import thread as _thread import threading as _threading except ImportError: import dummy_thread as _thread import dummy_threading as _threading # check for fcntl module try: sys.getwindowsversion() has_flock = False except: try: import fcntl has_flock = True except ImportError: has_flock = False class NameLock: """a proxy for an RLock object that is stored in a name based registry. Multiple threads can get a reference to the same RLock based on the name alone, and synchronize operations related to that name. """ locks = WeakValuedRegistry() class NLContainer: """cant put Lock as a weakref""" def __init__(self, reentrant): if reentrant: self.lock = _threading.RLock() else: self.lock = _threading.Lock() def __call__(self): return self.lock def __init__(self, identifier = None, reentrant = False): self.lock = self._get_lock(identifier, reentrant) def acquire(self, wait = True): return self.lock().acquire(wait) def release(self): self.lock().release() def _get_lock(self, identifier, reentrant): if identifier is None: return NameLock.NLContainer(reentrant) return NameLock.locks.get(identifier, lambda: NameLock.NLContainer(reentrant)) synchronizers = WeakValuedRegistry() def Synchronizer(identifier = None, use_files = False, lock_dir = None, digest_filenames = True): """ returns an object that synchronizes a block against many simultaneous read operations and several synchronized write operations. Write operations are assumed to be much less frequent than read operations, and receive precedence when they request a write lock. uses strategies to determine if locking is performed via threading objects or file objects. the identifier identifies a name this Synchronizer is synchronizing against. All synchronizers of the same identifier will lock against each other, within the effective thread/process scope. use_files determines if this synchronizer will lock against thread mutexes or file locks. this sets the effective scope of the synchronizer, i.e. it will lock against other synchronizers in the same process, or against other synchronizers referencing the same filesystem referenced by lock_dir. the acquire/relase methods support nested/reentrant operation within a single thread via a recursion counter, so that only the outermost call to acquire/release has any effect. """ if not has_flock: use_files = False if use_files: # FileSynchronizer is one per thread return synchronizers.sync_get("file_%s_%s" % (identifier, _thread.get_ident()), lambda: FileSynchronizer(identifier, lock_dir, digest_filenames)) else: # ConditionSynchronizer is shared among threads return synchronizers.sync_get("condition_%s" % identifier, lambda: ConditionSynchronizer(identifier)) class SyncState: """used to track the current thread's reading/writing state as well as reentrant block counting""" def __init__(self): self.reentrantcount = 0 self.writing = False self.reading = False class SynchronizerImpl(object): """base for the synchronizer implementations. the acquire/release methods keep track of re-entrant calls within the current thread, and delegate to the do_XXX methods when appropriate.""" def __init__(self, *args, **params): pass def release_read_lock(self): state = self.state if state.writing: raise "lock is in writing state" if not state.reading: raise "lock is not in reading state" if state.reentrantcount == 1: self.do_release_read_lock() state.reading = False state.reentrantcount -= 1 def acquire_read_lock(self, wait = True): state = self.state if state.writing: raise "lock is in writing state" if state.reentrantcount == 0: x = self.do_acquire_read_lock(wait) if (wait or x): state.reentrantcount += 1 state.reading = True return x elif state.reading: state.reentrantcount += 1 return True def release_write_lock(self): state = self.state if state.reading: raise "lock is in reading state" if not state.writing: raise "lock is not in writing state" if state.reentrantcount == 1: self.do_release_write_lock() state.writing = False state.reentrantcount -= 1 def acquire_write_lock(self, wait = True): state = self.state if state.reading: raise "lock is in reading state" if state.reentrantcount == 0: x = self.do_acquire_write_lock(wait) if (wait or x): state.reentrantcount += 1 state.writing = True return x elif state.writing: state.reentrantcount += 1 return True def do_release_read_lock():raise NotImplementedError() def do_acquire_read_lock():raise NotImplementedError() def do_release_write_lock():raise NotImplementedError() def do_acquire_write_lock():raise NotImplementedError() class FileSynchronizer(SynchronizerImpl): """a synchronizer using lock files. as it relies upon flock(), which is not safe to use with the same file descriptor among multiple threads (one file descriptor per thread is OK), a separate FileSynchronizer must exist in each thread.""" def __init__(self, identifier, lock_dir, digest_filenames): self.state = SyncState() if lock_dir is None: lock_dir = tempfile.gettempdir() else: lock_dir = lock_dir self.encpath = EncodedPath(lock_dir, [identifier], extension = '.lock', digest = digest_filenames) self.filename = self.encpath.path self.opened = False self.filedesc = None def _open(self, mode): if not self.opened: try: self.filedesc = os.open(self.filename, mode) except OSError, e: self.encpath.verify_directory() self.filedesc = os.open(self.filename, mode) self.opened = True def do_acquire_read_lock(self, wait): self._open(os.O_CREAT | os.O_RDONLY) if not wait: try: fcntl.flock(self.filedesc, fcntl.LOCK_SH | fcntl.LOCK_NB) ret = True except IOError: ret = False return ret else: fcntl.flock(self.filedesc, fcntl.LOCK_SH) return True def do_acquire_write_lock(self, wait): self._open(os.O_CREAT | os.O_WRONLY) if not wait: try: fcntl.flock(self.filedesc, fcntl.LOCK_EX | fcntl.LOCK_NB) ret = True except IOError: ret = False return ret else: fcntl.flock(self.filedesc, fcntl.LOCK_EX); return True def do_release_read_lock(self): self.release_all_locks() def do_release_write_lock(self): self.release_all_locks() def release_all_locks(self): if self.opened: fcntl.flock(self.filedesc, fcntl.LOCK_UN) os.close(self.filedesc) self.opened = False def __del__(self): if os.access(self.filename, os.F_OK): try: os.remove(self.filename) except OSError: # occasionally another thread beats us to it pass class ConditionSynchronizer(SynchronizerImpl): """a synchronizer using a Condition. this synchronizer is based on threading.Lock() objects and therefore must be shared among threads.""" def __init__(self, identifier): self.tlocalstate = ThreadLocal(creator = lambda: SyncState()) # counts how many asynchronous methods are executing self.async = 0 # pointer to thread that is the current sync operation self.current_sync_operation = None # condition object to lock on self.condition = _threading.Condition(_threading.Lock()) state = property(lambda self: self.tlocalstate()) def do_acquire_read_lock(self, wait = True): self.condition.acquire() # see if a synchronous operation is waiting to start # or is already running, in which case we wait (or just # give up and return) if wait: while self.current_sync_operation is not None: self.condition.wait() else: if self.current_sync_operation is not None: self.condition.release() return False self.async += 1 self.condition.release() if not wait: return True def do_release_read_lock(self): self.condition.acquire() self.async -= 1 # check if we are the last asynchronous reader thread # out the door. if self.async == 0: # yes. so if a sync operation is waiting, notifyAll to wake # it up if self.current_sync_operation is not None: self.condition.notifyAll() elif self.async < 0: raise "Synchronizer error - too many release_read_locks called" self.condition.release() def do_acquire_write_lock(self, wait = True): self.condition.acquire() # here, we are not a synchronous reader, and after returning, # assuming waiting or immediate availability, we will be. if wait: # if another sync is working, wait while self.current_sync_operation is not None: self.condition.wait() else: # if another sync is working, # we dont want to wait, so forget it if self.current_sync_operation is not None: self.condition.release() return False # establish ourselves as the current sync # this indicates to other read/write operations # that they should wait until this is None again self.current_sync_operation = _threading.currentThread() # now wait again for asyncs to finish if self.async > 0: if wait: # wait self.condition.wait() else: # we dont want to wait, so forget it self.current_sync_operation = None self.condition.release() return False self.condition.release() if not wait: return True def do_release_write_lock(self): self.condition.acquire() if self.current_sync_operation != _threading.currentThread(): raise "Synchronizer error - current thread doesnt have the write lock" # reset the current sync operation so # another can get it self.current_sync_operation = None # tell everyone to get ready self.condition.notifyAll() # everyone go !! self.condition.release() PK—tö4myghtyutils/__init__.pyPK—tö4€õþ ŒEŒEmyghtyutils/util.py# $Id: util.py,v 1.1.1.1 2006/01/12 20:54:38 classic Exp $ # util.py - utility functions for Myghty # Copyright (C) 2004, 2005 Michael Bayer mike_mp@zzzcomputing.com # # This module is part of Myghty and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php # __all__ = ["OrderedDict", "ThreadLocal", "Value", "InheritedDict", "ConstructorClone", "Registry", "WeakValuedRegistry", "SyncDict", "LRUCache", "argdict", "EncodedPath", "pid", "thread_id", "verify_directory", "PrefixArgs", "module"] try: import thread as _thread import threading as _threading except ImportError: import dummy_thread as _thread import dummy_threading as _threading import weakref, inspect, sha, string, os, UserDict, copy, sys, imp, re, stat, types, time def thread_id(): return _thread.get_ident() def pid(): return os.getpid() def verify_directory(dir): """verifies and creates a directory. tries to ignore collisions with other threads and processes.""" tries = 0 while not os.access(dir, os.F_OK): try: tries += 1 os.makedirs(dir, 0750) except: if tries > 5: raise def module(name): """imports a module, in the ordinary way, by string name""" mod = __import__(name) components = name.split('.') for comp in components[1:]: mod = getattr(mod, comp) return mod class argdict(dict): """supports the argument constructor form of dict which doesnt seem to be present in python 2.2""" def __init__(self, **params): dict.__init__(self) self.update(params) class Value: """allows pass-by-reference operations""" def __init__(self, value = None): self.value = value def __call__(self, *arg): if len(arg): self.assign(arg[0]) else: return self.value def __str__(self): return str(self.value) def assign(self, value): self.value = value class ThreadLocal: """stores a value on a per-thread basis""" def __init__(self, value = None, default = None, creator = None): self.dict = {} self.default = default self.creator = creator if value: self.put(value) def __call__(self, *arg): if len(arg): self.put(arg[0]) else: return self.get() def __str__(self): return str(self.get()) def assign(self, value): self.dict[_thread.get_ident()] = value def put(self, value): self.assign(value) def exists(self): return self.dict.has_key(_thread.get_ident()) def get(self, *args, **params): if not self.dict.has_key(_thread.get_ident()): if self.default is not None: self.put(self.default) elif self.creator is not None: self.put(self.creator(*args, **params)) return self.dict[_thread.get_ident()] def remove(self): del self.dict[_thread.get_ident()] class OrderedDict(UserDict.DictMixin): """A Dictionary that keeps its own internal ordering""" def __init__(self, values = None): self.list = [] self.dict = {} if values is not None: for val in values: self.update(val) def keys(self): return self.list def update(self, dict): for key in dict.keys(): self.__setitem__(key, dict[key]) def values(self): return map(lambda key: self[key], self.list) def __iter__(self): return iter(self.list) def itervalues(self): return iter([self[key] for key in self.list]) def iterkeys(self):return self.__iter__() def iteritems(self): return iter([(key, self[key]) for key in self.keys()]) def __delitem__(self, key): del self.dict[key] del self.list[self.list.index(key)] def __setitem__(self, key, object): if not self.has_key(key): self.list.append(key) self.dict.__setitem__(key, object) def __getitem__(self, key): return self.dict.__getitem__(key) class InheritedDict(UserDict.DictMixin): """a dictionary that can defer lookups to a second dictionary if the key is not found locally.""" def __init__(self, dict, superfunc): self.dict = dict self.superfunc = superfunc def __call__(self, key = None, value = None): if key is None and value is None: return self.dict elif value is None: try: return self.__getitem__(key) except KeyError: return None else: self.__setitem__(key, value) def __getitem__(self, key): dict = self.dict if dict.has_key(key): return dict[key] else: parent = self.superfunc() if parent is not None: return parent[key] raise KeyError(key) def __setitem__(self, key, value): self.dict[key] = value def __delitem__(self, key): del self.dict[key] def keys(self): return self.dict.keys() def __contains__(self, key): return self.has_key(key) def has_key(self, key): if self.dict.has_key(key): return True parent = self.superfunc() if parent is not None: return parent.has_key(key) return False class ConstructorClone: """cloning methods that take additional parameters. one method is a straight shallow copy, the other recreates the object via its constructor. both methods assume a relationship between the given parameters and the attribute names of the object.""" def __init__(self, instance, **params): self.classobj = instance.__class__ self.instance = instance self.params = params def copyclone(self): cl = copy.copy(self.instance) for key, value in self.params.iteritems(): setattr(cl, key, value) return cl # store the argument specs in a static hash argspecs = {} def clone(self): """creates a new instance of the class using the regular class constructor. the arguments to the constructor are divined from inspecting the parameter names, and pulling those parameters from the original instance's attributes. this is essentially a quickie cheater way to get a clone of an object if you can name your instance variables the same as that of the constructor arguments. """ key = self.classobj.__module__ + "." + self.classobj.__name__ if not ConstructorClone.argspecs.has_key(key): argspec = inspect.getargspec(self.classobj.__init__.im_func) argnames = argspec[0] or [] defaultvalues = argspec[3] or [] (requiredargs, namedargs) = ( argnames[0:len(argnames) - len(defaultvalues)], argnames[len(argnames) - len(defaultvalues):] ) ConstructorClone.argspecs[key] = (requiredargs, namedargs) (requiredargs, namedargs) = ConstructorClone.argspecs[key] newargs = [] newparams = {} addlparams = self.params.copy() for arg in requiredargs: if arg == 'self': continue elif self.params.has_key(arg): newargs.append(self.params[arg]) else: newargs.append(getattr(self.instance, arg)) if addlparams.has_key(arg): del addlparams[arg] for arg in namedargs: if addlparams.has_key(arg): del addlparams[arg] if self.params.has_key(arg): newparams[arg] = self.params[arg] else: if hasattr(self.instance, arg): newparams[arg] = getattr(self.instance, arg) else: raise "instance has no attribute '%s'" % arg newparams.update(addlparams) return self.classobj(*newargs, **newparams) class PrefixArgs: """extracts from the given argument dictionary all values with a key '' and stores a reference. """ def __init__(self, prefix): self.prefix = prefix self.params = {} self.prelen = len(prefix) def set_prefix_params(self, **params): """from the given dictionary, copies all values with keys in the form "" to this one.""" for key, item in params.iteritems(): if key[0:self.prelen] == self.prefix: self.params[key[self.prelen:]] = item def set_params(self, **params): """from the given dictionary, copies all key/values to this one.""" self.params.update(params) def get_params(self, **params): """returns a new dictionary with this object's values plus those in the given dictionary, with prefixes stripped from the keys.""" p = self.params.copy() for key, item in params.iteritems(): if key[0:self.prelen] == self.prefix: p[key[self.prelen:]] = item else: p[key] = item return p class SyncDict: """ an efficient/threadsafe singleton map algorithm, a.k.a. "get a value based on this key, and create if not found or not valid" paradigm: exists && isvalid ? get : create works with weakref dictionaries and the LRUCache to handle items asynchronously disappearing from the dictionary. use python 2.3.3 or greater ! a major bug was just fixed in Nov. 2003 that was driving me nuts with garbage collection/weakrefs in this section. """ def __init__(self, mutex, dictionary): self.mutex = mutex self.dict = dictionary def get(self, key, createfunc, mutex = None, isvalidfunc = None): """regular get method. returns the object asynchronously, if present and also passes the optional isvalidfunc, else defers to the synchronous get method which will create it.""" try: if self.has_key(key): return self._get_obj(key, createfunc, mutex, isvalidfunc) else: return self.sync_get(key, createfunc, mutex, isvalidfunc) except KeyError: return self.sync_get(key, createfunc, mutex, isvalidfunc) def sync_get(self, key, createfunc, mutex = None, isvalidfunc = None): if mutex is None: mutex = self.mutex mutex.acquire() try: try: if self.has_key(key): return self._get_obj(key, createfunc, mutex, isvalidfunc, create = True) else: return self._create(key, createfunc) except KeyError: return self._create(key, createfunc) finally: mutex.release() def _get_obj(self, key, createfunc, mutex, isvalidfunc, create = False): obj = self[key] if isvalidfunc is not None and not isvalidfunc(obj): if create: return self._create(key, createfunc) else: return self.sync_get(key, createfunc, mutex, isvalidfunc) else: return obj def _create(self, key, createfunc): obj = createfunc() self[key] = obj return obj def has_key(self, key): return self.dict.has_key(key) def __contains__(self, key): return self.dict.__contains__(key) def __getitem__(self, key): return self.dict.__getitem__(key) def __setitem__(self, key, value): self.dict.__setitem__(key, value) def __delitem__(self, key): return self.dict.__delitem__(key) class Registry(SyncDict): """a registry object.""" def __init__(self): SyncDict.__init__(self, _threading.Lock(), {}) class WeakValuedRegistry(SyncDict): """a registry that stores objects only as long as someone has a reference to them.""" def __init__(self): # weakrefs apparently can trigger the __del__ method of other # unreferenced objects, when you create a new reference. this can occur # when you place new items into the WeakValueDictionary. if that __del__ # method happens to want to access this same registry, well, then you need # the RLock instead of a regular lock, since at the point of dictionary # insertion, we are already inside the lock. SyncDict.__init__(self, _threading.RLock(), weakref.WeakValueDictionary()) class LRUCache(SyncDict): """a cache (mapping class) that stores only a certain number of elements, and discards its least recently used element when full.""" class ListElement: def __init__(self, key, value): self.key = key self.setvalue(value) def setvalue(self, value): self.value = value if hasattr(value, 'size'): self.size = value.size else: self.size = 1 def __init__(self, size, deletefunc = None, sizethreshhold = .2): SyncDict.__init__(self, _threading.Lock(), {}) self.size = size self.maxelemsize = sizethreshhold * size self.head = None self.tail = None self.deletefunc = deletefunc self.currentsize = 0 # inner mutex to synchronize list manipulation # operations independently of the SyncDict self.listmutex = _threading.Lock() def __setitem__(self, key, value): self.listmutex.acquire() try: existing = self.dict.get(key, None) if existing is None: element = LRUCache.ListElement(key, value) #if element.size > self.maxelemsize: return self.dict[key] = element self._insertElement(element) else: #if element.size > self.maxelemsize: #del self.dict[key] #self._removeElement(element) oldsize = existing.size existing.setvalue(value) self.currentsize += (existing.size - oldsize) self._updateElement(existing) self._manageSize() finally: self.listmutex.release() def __getitem__(self, key): self.listmutex.acquire() try: element = self.dict[key] self._updateElement(element) return element.value finally: self.listmutex.release() def __contains__(self, key): return self.dict.has_key(key) def has_key(self, key): return self.dict.has_key(key) def _insertElement(self, element): # zero-length elements are not managed in the LRU queue since they # have no affect on the total size if element.size == 0: return element.previous = None element.next = self.head if self.head is not None: self.head.previous = element else: self.tail = element self.head = element self.currentsize += element.size self._manageSize() def _manageSize(self): # TODO: dont remove one element at a time, remove the # excess in one step while self.currentsize > self.size: oldelem = self.dict[self.tail.key] if self.deletefunc is not None: self.deletefunc(oldelem.value) self.currentsize -= oldelem.size del self.dict[self.tail.key] if self.tail != self.head: self.tail = self.tail.previous self.tail.next = None else: self.tail = None self.head = None def _updateElement(self, element): # zero-length elements are not managed in the LRU queue since they # have no affect on the total size if element.size == 0: return if self.head == element: return e = element.previous e.next = element.next if element.next is not None: element.next.previous = e else: self.tail = e element.previous = None element.next = self.head self.head.previous = element self.head = element # TODO: iteration class EncodedPath: """generates a unique file-accessible path from the given list of identifiers starting at the given root directory.""" def __init__(self, root, identifiers, extension = ".enc", depth = 3, verify = True, digest = True): ident = string.join(identifiers, "_") if digest: ident = sha.new(ident).hexdigest() tokens = [] for d in range(1, depth): tokens.append(ident[0:d]) dir = os.path.join(root, *tokens) if verify: verify_directory(dir) self.dir = dir self.path = os.path.join(dir, ident + extension) def verify_directory(self): verify_directory(self.dir) def get_path(self): return self.path PK–žC8rJÍÕÕmyghtyutils/buffer.pyc;ò s cCs>|io |iit|i|ƒƒn|ii|ƒdS(N(sselfsfiltersbufferswritesmapslist(sselfslist((s6build/bdist.darwin-8.0.1-x86/egg/myghtyutils/buffer.pys writelinesDs  cCsg|i oX|io=|iidƒ|ii|iiƒƒ|iidƒqc|iiƒndS(Ni( sselfs ignore_flushsparentsbuffersseekswritesreadstruncatesflush(sself((s6build/bdist.darwin-8.0.1-x86/egg/myghtyutils/buffer.pysflushJs   cCs$dt|iƒt|iƒfSdS(Ns/Hierarchical Buffer, enclosing %s. Parent: %s(sreprsselfsbuffersparent(sself((s6build/bdist.darwin-8.0.1-x86/egg/myghtyutils/buffer.pys__repr__Ss( s__name__s __module__s__doc__sNonesFalses__init__s add_childstruncateswrites writelinessflushs__repr__(((s6build/bdist.darwin-8.0.1-x86/egg/myghtyutils/buffer.pysHierarchicalBuffer)s      s LogFormattercBs2tZeed„Zd„Zd„Zd„ZRS(NcCs/ti||ƒ||_||_||_dS(N(sBufferDecorators__init__sselfsbuffers identifiers id_threadss autoflush(sselfsbuffers identifiers id_threadss autoflush((s6build/bdist.darwin-8.0.1-x86/egg/myghtyutils/buffer.pys__init__Ys  cCsR|io*d|itƒtƒti|ƒfSnd|iti|ƒfSdS(Ns[%s] [pid:%d tid:%d] %ss[%s] %s(sselfs id_threadss identifierspids thread_idsstringsrstripss(sselfss((s6build/bdist.darwin-8.0.1-x86/egg/myghtyutils/buffer.pys _formatline_s *cCs5|ii|i|ƒƒ|io|iƒndS(N(sselfsbufferswrites _formatlinesss autoflushsflush(sselfss((s6build/bdist.darwin-8.0.1-x86/egg/myghtyutils/buffer.pyswritees cCs.x'|D]}|ii|i|ƒƒqWdS(N(slinesslinesselfsbufferswrites _formatline(sselfslinessline((s6build/bdist.darwin-8.0.1-x86/egg/myghtyutils/buffer.pys writelinesjs(s__name__s __module__sFalsesTrues__init__s _formatlineswrites writelines(((s6build/bdist.darwin-8.0.1-x86/egg/myghtyutils/buffer.pys LogFormatterXs  ( s__doc__sutilsStringIOssyssstringsobjectsBufferDecoratorsFunctionBuffers LinePrintersHierarchicalBuffers LogFormatter(s LogFormatters LinePrintersstringsStringIOssyssHierarchicalBuffersFunctionBuffersBufferDecorator((s6build/bdist.darwin-8.0.1-x86/egg/myghtyutils/buffer.pys? s  /PK–žC8ò_9È„¨„¨myghtyutils/container.pyc;ò >pÂDc @sydkZdkZdkZdkZdkZdkZdkTdkTdk Z dddddddd d d d d g Z d„Z dfd„ƒYZ dfd„ƒYZ de fd„ƒYZdfd„ƒYZd efd„ƒYZde fd„ƒYZdefd„ƒYZd e fd„ƒYZdefd„ƒYZeZeZd e fd„ƒYZd efd„ƒYZdS(N(s*sNamespaceContextsContainerContexts ContainersMemoryContainers DBMContainersNamespaceManagersMemoryNamespaceManagersDBMNamespaceManagers FileContainersFileNamespaceManagersCreationAbortedErrorscontainer_registrycCsq|idƒo0|d}d|}tt|ƒi|ƒ}ntit }t i |ƒ|}t||ƒSdS(Nsext:is myghty.ext.(snames startswithsmodnamesgetattrs __import__sextsmodssyssmoduless__name__sstrings capitalizes classtypescname(snames classtypesmodnamescnamesmod((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pyscontainer_registrys   cBs&tZdZed„Zed„ZRS(s-initial context supplied to NamespaceManagerscCs ||_dS(N(slog_filesself(sselfslog_file((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys__init__$scCsn|itj oZ|tj o&d|ii|i|i|f}nd|i|f}|ii |ƒndS(Ns[%s:%s:%s] %s s[%s] %s ( sselfslog_filesNones containers __class__s__name__snsms namespaceskeysmessageswrite(sselfsmessagesnsms container((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdebug's  &(s__name__s __module__s__doc__sNones__init__sdebug(((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysNamespaceContext!s  cBsãtZdZd„Zd„Zd„Zed„Zd„Zd„Z d„Z d„Z d „Z d „Z d „Zd „Zd „Zd„Zd„Zd„Zed„Zd„Zed„Zed„Zd„Zed„ZRS(sˆhandles dictionary operations and locking for a namespace of values. the implementation for setting and retrieving the namespace data is handled by subclasses. acts as a service for a Container, which stores and retreives a particular key from the namespace, coupled with a "stored time" setting. NamespaceManager may be used alone, or may be privately managed by one or more Container objects. Container objects provide per-key services like automatic expiration and recreation of individual keys and can manange many types of NamespaceManagers for one or more particular namespaces simultaneously. the class supports locking relative to its name. many namespacemanagers within multiple threads or across multiple processes must read/write synchronize their access to the actual dictionary of data referenced by the name. cKs.||_||_d|_tiƒ|_dS(Ni(scontextsselfs namespacesopenerss _threadingsLocksmutex(sselfscontexts namespacesparams((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys__init__Es   cCs tƒ‚dS(N(sNotImplementedError(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_acquire_read_lockOscCs tƒ‚dS(N(sNotImplementedError(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_release_read_lockPscCs tƒ‚dS(N(sNotImplementedError(sselfswait((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_acquire_write_lockQscCs tƒ‚dS(N(sNotImplementedError(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_release_write_lockRscCs tƒ‚dS(N(sNotImplementedError(sselfsflags((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_openTscCs tƒ‚dS(N(sNotImplementedError(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_closeUscCs tƒ‚dS(s1removes this namespace from wherever it is storedN(sNotImplementedError(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys do_removeWscCs|i|ƒSdS(N(sselfs __contains__skey(sselfskey((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pyshas_key[scCs tƒ‚dS(N(sNotImplementedError(sselfskey((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys __getitem__^scCs tƒ‚dS(N(sNotImplementedError(sselfskeysvalue((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys __setitem__ascCs tƒ‚dS(N(sNotImplementedError(sselfskey((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys __contains__dscCs tƒ‚dS(N(sNotImplementedError(sselfskey((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys __delitem__gscCs tƒ‚dS(N(sNotImplementedError(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pyskeysjscCs!|iƒ|iddtƒdS(sØacquires a read lock for this namespace, and insures that the datasource has been opened for reading if it is not already opened. acquire/release supports reentrant/nested operation.srs checkcountN(sselfsdo_acquire_read_locksopensTrue(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysacquire_read_lockms cCs|idtƒ|iƒdS(såreleases the read lock for this namespace, and possibly closes the datasource, if it was opened as a product of the read lock's acquire/release block. acquire/release supports reentrant/nested operation.s checkcountN(sselfsclosesTruesdo_release_read_lock(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysrelease_read_lockwscCs<|i|ƒ}|p|o|iddtƒn|SdS(sÑacquires a write lock for this namespace, and insures that the datasource has been opened for writing if it is not already opened. acquire/release supports reentrant/nested operation.scs checkcountN(sselfsdo_acquire_write_lockswaitsrsopensTrue(sselfswaitsr((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysacquire_write_locks cCs|idtƒ|iƒdS(sçreleases the write lock for this namespace, and possibly closes the datasource, if it was opened as a product of the write lock's acquire/release block. acquire/release supports reentrant/nested operation.s checkcountN(sselfsclosesTruesdo_release_write_lock(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysrelease_write_lockŒscCsw|iiƒzU|o4|idjo|i|ƒn|id7_n|i|ƒd|_Wd|iiƒXdS(säopens the datasource for this namespace. the checkcount flag indicates an "opened" counter should be checked for zero before performing the open operation, which is incremented by one regardless.iiN(sselfsmutexsacquires checkcountsopenerssdo_opensflagssrelease(sselfsflagss checkcount((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysopen–s   cCs…|iiƒzc|o1|id8_|idjo|iƒqon(|idjo|iƒnd|_Wd|iiƒXdS(såcloses the datasource for this namespace. the checkcount flag indicates an "opened" counter should be checked for zero before performing the close operation, which is otherwise decremented by one.iiN(sselfsmutexsacquires checkcountsopenerssdo_closesrelease(sselfs checkcount((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysclose¨s  cCs:|iƒz|idtƒ|iƒWd|iƒXdS(Ns checkcount(sselfsdo_acquire_write_locksclosesFalses do_removesdo_release_write_lock(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysremove¼s  cCs|ii|||ƒdS(N(sselfscontextsdebugsmessages container(sselfsmessages container((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdebugÄs(s__name__s __module__s__doc__s__init__sdo_acquire_read_locksdo_release_read_locksTruesdo_acquire_write_locksdo_release_write_locksdo_opensdo_closes do_removeshas_keys __getitem__s __setitem__s __contains__s __delitem__skeyssacquire_read_locksrelease_read_locksacquire_write_locksrelease_write_locksFalsesopensclosesremovesNonesdebug(((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysNamespaceManager1s.                 cBs,tZdZed„Zd„Zd„ZRS(sïinitial context supplied to Containers. Keeps track of namespacemangers keyed off of namespace names and container types. also keeps namespacemanagers thread local for nsm instances that arent threadsafe (i.e. gdbm) cCsti||ƒh|_dS(N(sNamespaceContexts__init__sselfslog_filesregistry(sselfslog_file((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys__init__ÒscKssttiƒƒd|iid|}y|i |SWn5t j o)|i i ||i |||ƒSnXdS(Ns|(sstrs_threads get_idents containers __class__s__name__s namespaceskeysselfsregistrysKeyErrors setdefaults create_nsmsparams(sselfs namespaces containersparamsskey((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysget_namespace_managerÖs (cKs#|id|d||}|SdS(Nscontexts namespace(s containersdo_create_namespace_managersselfs namespacesparamssnsm(sselfs namespaces containersparamssnsm((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys create_nsmßs(s__name__s __module__s__doc__sNones__init__sget_namespace_managers create_nsm(((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysContainerContextÉs   cBsìtZdZeeed„Zd„Zd„Zed„Zd„Z d„Z d„Z d„Z d „Z d „Zd „Zd „Zed „Zd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„ZRS(slrepresents a value, its stored time, and a value creation function corresponding to a particular key in a particular namespace. handles storage and retrieval of its value via a single NamespaceManager, as well as handling expiration times and an optional creation function that can create or recreate its value when needed. the Container performs locking operations on the NamespaceManager, including a pretty intricate one for get_value with a creation function, so its best not to pass a NamespaceManager that has been externally locked or open, as it stands currently (i hope to improve on this). Managing multiple Containers for a set of keys within a certain namespace allows management of multiple namespace implementations, expiration properties, and thread/process synchronization, on a per-key basis. cKsV||_||_||_||_d|_|i||||_ |i |dS(srcreate a container that stores one cached object. createfunc - a function that will create the value. this function is called when value is None or expired. the createfunc call is also synchronized against any other threads or processes calling this cache. expiretime - time in seconds that the item expires. iÿÿÿÿN( skeysselfs createfuncs expiretimes starttimes storedtimescontextsget_namespace_managers namespacesparamssnamespacemanagersdo_init(sselfskeyscontexts namespaces createfuncs expiretimes starttimesparams((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys__init__÷s     cCs|iiƒdS(N(sselfsnamespacemanagersacquire_read_lock(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysacquire_read_lock scCs|iiƒdS(N(sselfsnamespacemanagersrelease_read_lock(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysrelease_read_lock scCs|ii|ƒSdS(N(sselfsnamespacemanagersacquire_write_lockswait(sselfswait((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysacquire_write_lockscCs|iiƒdS(N(sselfsnamespacemanagersrelease_write_lock(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysrelease_write_lockscCs|ii||ƒdS(N(sselfsnamespacemanagersdebugsmessage(sselfsmessage((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdebugscKs tƒ‚dS(scsubclasses should return a newly created instance of their corresponding NamespaceManager.N(sNotImplementedError(sselfscontexts namespacesparams((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_create_namespace_managerscKsdS(sYsubclasses can perform general initialization. optional template method.N((sselfsparams((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_initscCs|i|iSdS(sªretrieves the native stored value of this container, regardless of if its expired, or raise KeyError if no value is defined. optionally a template method.N(sselfsnamespacemanagerskey(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys do_get_value$scCs||i|iØs( sNamespaceManagers__init__sselfscontexts namespacesparamss SynchronizersFalseslocksMemoryNamespaceManagers namespacessgets dictionary(sselfscontexts namespacesparams((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys__init__ÓscCs|iiƒdS(N(sselfslocksacquire_read_lock(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_acquire_read_lockÚscCs|iiƒdS(N(sselfslocksrelease_read_lock(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_release_read_lockÛscCs|ii|ƒSdS(N(sselfslocksacquire_write_lockswait(sselfswait((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_acquire_write_lockÜscCs|iiƒdS(N(sselfslocksrelease_write_lock(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_release_write_lockÝscOsdS(N((sselfsargssparams((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysopenáscOsdS(N((sselfsargssparams((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pyscloseâscCs|i|SdS(N(sselfs dictionaryskey(sselfskey((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys __getitem__äscCs|ii|ƒSdS(N(sselfs dictionarys __contains__skey(sselfskey((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys __contains__æscCs|ii|ƒSdS(N(sselfs dictionarys __contains__skey(sselfskey((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pyshas_keyéscCs||i||i|iƒ o&|ii|idƒ}|iƒndS(Nsc(sselfs file_existssfiles dbmmodulesopensgsclose(sselfsg((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys _checkfile8scCs›g}ti|itiƒo|i|iƒnx]ddddfD]I}ti|iti|tiƒo|i|iti|ƒqFqFW|SdS(Nspagsdirsdbsdat( slistsossaccesssselfsfilesF_OKsappendsextsextsep(sselfslistsext((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys get_filenames=s$#cCs|iiƒdS(N(sselfslocksacquire_read_lock(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_acquire_read_lockHscCs|iiƒdS(N(sselfslocksrelease_read_lock(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_release_read_lockKscCs|ii|ƒSdS(N(sselfslocksacquire_write_lockswait(sselfswait((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_acquire_write_lockNscCs|iiƒdS(N(sselfslocksrelease_write_lock(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_release_write_lockQscCss|id|iƒy|ii|i|ƒ|_Wn9|iiƒ|i ƒ|ii|i|ƒ|_nXdS(Nsopening dbm file %s( sselfsdebugsfiles dbmmodulesopensflagssdbmsencpathsverify_directorys _checkfile(sselfsflags((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_openTs  cCs9|itj o%|id|iƒ|iiƒndS(Nsclosing dbm file %s(sselfsdbmsNonesdebugsfilesclose(sself((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pysdo_closecscCs(x!|iƒD]}ti|ƒq WdS(N(sselfs get_filenamessfsossremove(sselfsf((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys do_removehs cCsti|i|ƒSdS(N(scPicklesloadssselfsdbmskey(sselfskey((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys __getitem__lscCs|ii|ƒSdS(N(sselfsdbmshas_keyskey(sselfskey((s9build/bdist.darwin-8.0.1-x86/egg/myghtyutils/container.pys __contains__oscCsti|ƒ|i| 0: self.do_close() self.openers = 0 finally: self.mutex.release() def remove(self): self.do_acquire_write_lock() try: self.close(checkcount = False) self.do_remove() finally: self.do_release_write_lock() def debug(self, message, container = None): self.context.debug(message, self, container) class ContainerContext(NamespaceContext): """initial context supplied to Containers. Keeps track of namespacemangers keyed off of namespace names and container types. also keeps namespacemanagers thread local for nsm instances that arent threadsafe (i.e. gdbm) """ def __init__(self, log_file = None): NamespaceContext.__init__(self, log_file) self.registry = {} def get_namespace_manager(self, namespace, container, **params): key = str(_thread.get_ident()) + "|" + container.__class__.__name__ + "|" + namespace try: return self.registry[key] except KeyError: return self.registry.setdefault(key, self.create_nsm(namespace, container, **params)) def create_nsm(self, namespace, container, **params): nsm = container.do_create_namespace_manager(context = self, namespace = namespace, **params) return nsm class Container: """represents a value, its stored time, and a value creation function corresponding to a particular key in a particular namespace. handles storage and retrieval of its value via a single NamespaceManager, as well as handling expiration times and an optional creation function that can create or recreate its value when needed. the Container performs locking operations on the NamespaceManager, including a pretty intricate one for get_value with a creation function, so its best not to pass a NamespaceManager that has been externally locked or open, as it stands currently (i hope to improve on this). Managing multiple Containers for a set of keys within a certain namespace allows management of multiple namespace implementations, expiration properties, and thread/process synchronization, on a per-key basis. """ def __init__(self, key, context, namespace, createfunc = None, expiretime = None, starttime = None, **params): """create a container that stores one cached object. createfunc - a function that will create the value. this function is called when value is None or expired. the createfunc call is also synchronized against any other threads or processes calling this cache. expiretime - time in seconds that the item expires. """ self.key = key self.createfunc = createfunc self.expiretime = expiretime self.starttime = starttime self.storedtime = -1 self.namespacemanager = context.get_namespace_manager(namespace, self, **params) self.do_init(**params) def acquire_read_lock(self): self.namespacemanager.acquire_read_lock() def release_read_lock(self): self.namespacemanager.release_read_lock() def acquire_write_lock(self, wait = True): return self.namespacemanager.acquire_write_lock(wait) def release_write_lock(self): self.namespacemanager.release_write_lock() def debug(self, message): self.namespacemanager.debug(message, self) def do_create_namespace_manager(self, context, namespace, **params): """subclasses should return a newly created instance of their corresponding NamespaceManager.""" raise NotImplementedError() def do_init(self, **params): """subclasses can perform general initialization. optional template method.""" pass def do_get_value(self): """retrieves the native stored value of this container, regardless of if its expired, or raise KeyError if no value is defined. optionally a template method.""" return self.namespacemanager[self.key] def do_set_value(self, value): """sets the raw value in this container. optionally a template method.""" self.namespacemanager[self.key] = value def do_clear_value(self): """clears the value of this container. subsequent do_get_value calls should raise KeyError. optionally a template method.""" if self.namespacemanager.has_key(self.key): del self.namespacemanager[self.key] def has_value(self): """returns true if the container has a value stored, regardless of it being expired or not. optionally a template method.""" self.acquire_read_lock() try: return self.namespacemanager.has_key(self.key) finally: self.release_read_lock() def lock_createfunc(self, wait = True): """required template method that locks this container's namespace and key to allow a single execution of the creation function.""" raise NotImplementedError() def unlock_createfunc(self): """required template method that unlocks this container's namespace and key when the creation function is complete.""" raise NotImplementedError() def can_have_value(self): """returns true if this container either has a non-expired value, or is capable of creating one via a creation function""" return self.has_current_value() or self.createfunc is not None def has_current_value(self): """returns true if this container has a non-expired value""" return self.has_value() and not self.is_expired() def stored_time(self): return self.storedtime def get_namespace_manager(self): return self.namespacemanager def get_all_namespaces(self): return self.namespacemanager.context._container_namespaces.values() def is_expired(self): """returns true if this container's value is expired, based on the last time get_value was called.""" return ( ( self.storedtime == -1 ) or ( self.starttime is not None and self.storedtime < self.starttime ) or ( self.expiretime is not None and time.time() >= self.expiretime + self.storedtime ) ) def get_value(self): """get_value performs a get with expiration checks on its namespacemanager. if a creation function is specified, a new value will be created if the existing value is nonexistent or has expired.""" self.acquire_read_lock() try: has_value = self.has_value() if has_value: [self.storedtime, value] = self.do_get_value() if not self.is_expired(): return value if not self.can_have_value(): raise KeyError(self.key) finally: self.release_read_lock() has_createlock = False if has_value: if not self.lock_createfunc(wait = False): self.debug("get_value returning old value while new one is created") return value else: self.debug("lock_creatfunc (didnt wait)") has_createlock = True if not has_createlock: self.debug("lock_createfunc (waiting)") self.lock_createfunc() self.debug("lock_createfunc (waited)") try: # see if someone created the value already self.acquire_read_lock() try: if self.has_value(): [self.storedtime, value] = self.do_get_value() if not self.is_expired(): return value finally: self.release_read_lock() self.debug("get_value creating new value") try: v = self.createfunc() except CreationAbortedError, e: raise self.set_value(v) return v finally: self.unlock_createfunc() self.debug("unlock_createfunc") def set_value(self, value): self.acquire_write_lock() try: self.storedtime = time.time() self.debug("set_value stored time %d" % self.storedtime) self.do_set_value([self.storedtime, value]) finally: self.release_write_lock() def clear_value(self): self.acquire_write_lock() try: self.debug("clear_value") self.do_clear_value() self.storedtime = -1 finally: self.release_write_lock() class CreationAbortedError(Exception): """a special exception that allows a creation function to abort what its doing""" def __init__(self, **params): self.params = params class MemoryNamespaceManager(NamespaceManager): namespaces = SyncDict(_threading.Lock(), {}) def __init__(self, context, namespace, **params): NamespaceManager.__init__(self, context, namespace, **params) self.lock = Synchronizer(identifier = "memorycontainer/namespacelock/%s" % self.namespace, use_files = False) self.dictionary = MemoryNamespaceManager.namespaces.get(self.namespace, lambda: {}) def do_acquire_read_lock(self): self.lock.acquire_read_lock() def do_release_read_lock(self): self.lock.release_read_lock() def do_acquire_write_lock(self, wait = True): return self.lock.acquire_write_lock(wait) def do_release_write_lock(self): self.lock.release_write_lock() # the open and close methods are totally overridden to eliminate # the unnecessary "open count" computation involved def open(self, *args, **params):pass def close(self, *args, **params):pass def __getitem__(self, key): return self.dictionary[key] def __contains__(self, key): return self.dictionary.__contains__(key) def has_key(self, key): return self.dictionary.__contains__(key) def __setitem__(self, key, value):self.dictionary[key] = value def __delitem__(self, key): del self.dictionary[key] def do_remove(self): self.dictionary.clear() def keys(self): return self.dictionary.keys() class MemoryContainer(Container): def do_init(self, **params): self.funclock = None def do_create_namespace_manager(self, context, namespace, **params): return MemoryNamespaceManager(context, namespace, **params) def lock_createfunc(self, wait = True): if self.funclock is None: self.funclock = NameLock(identifier = "memorycontainer/funclock/%s/%s" % (self.namespacemanager.namespace, self.key), reentrant = True) return self.funclock.acquire(wait) def unlock_createfunc(self): self.funclock.release() class DBMNamespaceManager(NamespaceManager): def __init__(self, context, namespace, dbmmodule = None, data_dir = None, dbm_dir = None, lock_dir = None, digest_filenames = True, **params): NamespaceManager.__init__(self, context, namespace, **params) if dbm_dir is not None: self.dbm_dir = dbm_dir elif data_dir is None: raise "data_dir or dbm_dir is required" else: self.dbm_dir = data_dir + "/container_dbm" if lock_dir is not None: self.lock_dir = lock_dir elif data_dir is None: raise "data_dir or lock_dir is required" else: self.lock_dir = data_dir + "/container_dbm_lock" if dbmmodule is None: import anydbm self.dbmmodule = anydbm else: self.dbmmodule = dbmmodule verify_directory(self.dbm_dir) verify_directory(self.lock_dir) self.dbm = None self.lock = Synchronizer(identifier = self.namespace, use_files = True, lock_dir = self.lock_dir, digest_filenames = digest_filenames) self.encpath = EncodedPath(root = self.dbm_dir, identifiers = [self.namespace], digest = digest_filenames, extension = '.dbm') self.file = self.encpath.path self.debug("data file %s" % self.file) self._checkfile() def file_exists(self, file): if os.access(file, os.F_OK): return True else: for ext in ('db', 'dat', 'pag', 'dir'): if os.access(file + os.extsep + ext, os.F_OK): return True return False def _checkfile(self): if not self.file_exists(self.file): g = self.dbmmodule.open(self.file, 'c') g.close() def get_filenames(self): list = [] if os.access(self.file, os.F_OK): list.append(self.file) for ext in ('pag', 'dir', 'db', 'dat'): if os.access(self.file + os.extsep + ext, os.F_OK): list.append(self.file + os.extsep + ext) return list def do_acquire_read_lock(self): self.lock.acquire_read_lock() def do_release_read_lock(self): self.lock.release_read_lock() def do_acquire_write_lock(self, wait = True): return self.lock.acquire_write_lock(wait) def do_release_write_lock(self): self.lock.release_write_lock() def do_open(self, flags): # caution: apparently gdbm handles arent threadsafe, they # are using flock(), and i would rather not have knowledge # of the "unlock" 'u' option just for that one dbm module. # therefore, neither is an individual instance of # this namespacemanager (of course, multiple nsm's # can exist for each thread). self.debug("opening dbm file %s" % self.file) try: self.dbm = self.dbmmodule.open(self.file, flags) except: self.encpath.verify_directory() self._checkfile() self.dbm = self.dbmmodule.open(self.file, flags) def do_close(self): if self.dbm is not None: self.debug("closing dbm file %s" % self.file) self.dbm.close() def do_remove(self): for f in self.get_filenames(): os.remove(f) def __getitem__(self, key): return cPickle.loads(self.dbm[key]) def __contains__(self, key): return self.dbm.has_key(key) def __setitem__(self, key, value): self.dbm[key] = cPickle.dumps(value) def __delitem__(self, key): del self.dbm[key] def keys(self): return self.dbm.keys() class DBMContainer(Container): def do_init(self, **params): self.funclock = None def do_create_namespace_manager(self, context, namespace, **params): return DBMNamespaceManager(context, namespace, **params) def lock_createfunc(self, wait = True): if self.funclock is None: self.funclock = Synchronizer(identifier = "dbmcontainer/funclock/%s" % self.namespacemanager.namespace, use_files = True, lock_dir = self.namespacemanager.lock_dir) return self.funclock.acquire_write_lock(wait) def unlock_createfunc(self): self.funclock.release_write_lock() DbmNamespaceManager = DBMNamespaceManager DbmContainer = DBMContainer class FileNamespaceManager(NamespaceManager): def __init__(self, context, namespace, data_dir = None, file_dir = None, lock_dir = None, digest_filenames = True, **params): NamespaceManager.__init__(self, context, namespace, **params) if file_dir is not None: self.file_dir = file_dir elif data_dir is None: raise "data_dir or file_dir is required" else: self.file_dir = data_dir + "/container_file" if lock_dir is not None: self.lock_dir = lock_dir elif data_dir is None: raise "data_dir or lock_dir is required" else: self.lock_dir = data_dir + "/container_file_lock" verify_directory(self.file_dir) verify_directory(self.lock_dir) self.lock = Synchronizer(identifier = self.namespace, use_files = True, lock_dir = self.lock_dir, digest_filenames = digest_filenames) self.file = EncodedPath(root = self.file_dir, identifiers = [self.namespace], digest = digest_filenames, extension = '.cache').path self.hash = {} self.debug("data file %s" % self.file) def file_exists(self, file): if os.access(file, os.F_OK): return True else: return False def do_acquire_read_lock(self): self.lock.acquire_read_lock() def do_release_read_lock(self): self.lock.release_read_lock() def do_acquire_write_lock(self, wait = True): return self.lock.acquire_write_lock(wait) def do_release_write_lock(self): self.lock.release_write_lock() def do_open(self, flags): if self.file_exists(self.file): fh = open(self.file, 'r') self.hash = cPickle.load(fh) fh.close() self.flags = flags def do_close(self): if self.flags is not None and (self.flags == 'c' or self.flags == 'w'): fh = open(self.file, 'w') cPickle.dump(self.hash, fh) fh.close() self.flags = None def do_remove(self): os.remove(self.file) self.hash = {} def __getitem__(self, key): return self.hash[key] def __contains__(self, key): return self.hash.has_key(key) def __setitem__(self, key, value): self.hash[key] = value def __delitem__(self, key): del self.hash[key] def keys(self): return self.hash.keys() class FileContainer(Container): def do_init(self, **params): self.funclock = None def do_create_namespace_manager(self, context, namespace, **params): return FileNamespaceManager(context, namespace, **params) def lock_createfunc(self, wait = True): if self.funclock is None: self.funclock = Synchronizer(identifier = "filecontainer/funclock/%s" % self.namespacemanager.namespace, use_files = True, lock_dir = self.namespacemanager.lock_dir) return self.funclock.acquire_write_lock(wait) def unlock_createfunc(self): self.funclock.release_write_lock() PK–žC8röCCmyghtyutils/synchronization.pyc;ò >pÂDc@s[ddddgZdkZdkZdkZdkZdkZdkTydkZdk Z Wn%e j odk Zdk Z nXyeiƒeZWn6ydkZeZWqÑe j o eZqÑXnXdfd„ƒYZeƒZeeeed„Zdfd „ƒYZd efd „ƒYZd efd „ƒYZdefd„ƒYZdS(s SynchronizersNameLocks _threadings_threadN(s*cBsWtZdZeƒZdfd„ƒYZeed„Ze d„Z d„Z d„Z RS(sßa proxy for an RLock object that is stored in a name based registry. Multiple threads can get a reference to the same RLock based on the name alone, and synchronize operations related to that name. s NLContainercBs tZdZd„Zd„ZRS(scant put Lock as a weakrefcCs-|otiƒ|_ntiƒ|_dS(N(s reentrants _threadingsRLocksselfslocksLock(sselfs reentrant((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys__init__.scCs |iSdS(N(sselfslock(sself((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys__call__3s(s__name__s __module__s__doc__s__init__s__call__(((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys NLContainer,s  cCs|i||ƒ|_dS(N(sselfs _get_locks identifiers reentrantslock(sselfs identifiers reentrant((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys__init__6scCs|iƒi|ƒSdS(N(sselfslocksacquireswait(sselfswait((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysacquire9scCs|iƒiƒdS(N(sselfslocksrelease(sself((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysrelease<scs;|tjotiˆƒSntii|‡d†ƒSdS(Ncs tiˆƒS(N(sNameLocks NLContainers reentrant((s reentrant(s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysDs(s identifiersNonesNameLocks NLContainers reentrantslockssget(sselfs identifiers reentrant((s reentrants?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys _get_lock?s ( s__name__s __module__s__doc__sWeakValuedRegistryslockss NLContainersNonesFalses__init__sTruesacquiresreleases _get_lock(((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysNameLock"s     csgt o t}n|o0tidˆtiƒf‡‡‡d†ƒSntidˆ‡d†ƒSdS(sY returns an object that synchronizes a block against many simultaneous read operations and several synchronized write operations. Write operations are assumed to be much less frequent than read operations, and receive precedence when they request a write lock. uses strategies to determine if locking is performed via threading objects or file objects. the identifier identifies a name this Synchronizer is synchronizing against. All synchronizers of the same identifier will lock against each other, within the effective thread/process scope. use_files determines if this synchronizer will lock against thread mutexes or file locks. this sets the effective scope of the synchronizer, i.e. it will lock against other synchronizers in the same process, or against other synchronizers referencing the same filesystem referenced by lock_dir. the acquire/relase methods support nested/reentrant operation within a single thread via a recursion counter, so that only the outermost call to acquire/release has any effect. s file_%s_%scstˆˆˆƒS(N(sFileSynchronizers identifierslock_dirsdigest_filenames((sdigest_filenamess identifierslock_dir(s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysjss condition_%scs tˆƒS(N(sConditionSynchronizers identifier((s identifier(s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysmsN(s has_flocksFalses use_filess synchronizersssync_gets identifiers_threads get_ident(s identifiers use_filesslock_dirsdigest_filenames((s identifierslock_dirsdigest_filenamess?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys SynchronizerKs  0s SyncStatecBstZdZd„ZRS(s\used to track the current thread's reading/writing state as well as reentrant block countingcCsd|_t|_t|_dS(Ni(sselfsreentrantcountsFalseswritingsreading(sself((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys__init__ss  (s__name__s __module__s__doc__s__init__(((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys SyncStateps sSynchronizerImplcBsetZdZd„Zd„Zed„Zd„Zed„Zd„Z d„Z d„Z d „Z RS( sºbase for the synchronizer implementations. the acquire/release methods keep track of re-entrant calls within the current thread, and delegate to the do_XXX methods when appropriate.cOsdS(N((sselfsargssparams((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys__init__|scCsl|i}|io d‚n|i o d‚n|idjo|iƒt|_n|id8_dS(Nslock is in writing stateslock is not in reading statei(sselfsstateswritingsreadingsreentrantcountsdo_release_read_locksFalse(sselfsstate((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysrelease_read_locks     cCs“|i}|io d‚n|idjoA|i|ƒ}|p|o|id7_t|_n|Sn"|io|id7_tSndS(Nslock is in writing stateii( sselfsstateswritingsreentrantcountsdo_acquire_read_lockswaitsxsTruesreading(sselfswaitsxsstate((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysacquire_read_lock‹s    cCsl|i}|io d‚n|i o d‚n|idjo|iƒt|_n|id8_dS(Nslock is in reading stateslock is not in writing statei(sselfsstatesreadingswritingsreentrantcountsdo_release_write_locksFalse(sselfsstate((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysrelease_write_lockšs     cCs“|i}|io d‚n|idjoA|i|ƒ}|p|o|id7_t|_n|Sn"|io|id7_tSndS(Nslock is in reading stateii( sselfsstatesreadingsreentrantcountsdo_acquire_write_lockswaitsxsTrueswriting(sselfswaitsxsstate((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysacquire_write_lock¦s    cCs tƒ‚dS(N(sNotImplementedError(((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysdo_release_read_lockµscCs tƒ‚dS(N(sNotImplementedError(((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysdo_acquire_read_lock¶scCs tƒ‚dS(N(sNotImplementedError(((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysdo_release_write_lock·scCs tƒ‚dS(N(sNotImplementedError(((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysdo_acquire_write_lock¸s( s__name__s __module__s__doc__s__init__srelease_read_locksTruesacquire_read_locksrelease_write_locksacquire_write_locksdo_release_read_locksdo_acquire_read_locksdo_release_write_locksdo_acquire_write_lock(((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysSynchronizerImplxs       sFileSynchronizercBsVtZdZd„Zd„Zd„Zd„Zd„Zd„Zd„Z d„Z RS( s÷a synchronizer using lock files. as it relies upon flock(), which is not safe to use with the same file descriptor among multiple threads (one file descriptor per thread is OK), a separate FileSynchronizer must exist in each thread.cCsutƒ|_|tjotiƒ}n|}t||gddd|ƒ|_ |i i |_ t |_t|_dS(Ns extensions.locksdigest(s SyncStatesselfsstateslock_dirsNonestempfiles gettempdirs EncodedPaths identifiersdigest_filenamessencpathspathsfilenamesFalsesopenedsfiledesc(sselfs identifierslock_dirsdigest_filenames((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys__init__Às  ! cCsu|i ofyti|i|ƒ|_Wn:tj o.}|i i ƒti|i|ƒ|_nXt |_ndS(N( sselfsopenedsossopensfilenamesmodesfiledescsOSErrorsesencpathsverify_directorysTrue(sselfsmodese((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys_openÎs  cCsˆ|ititiBƒ| oKy'ti|iti ti Bƒt }Wnt j o t}nX|Snti|iti ƒt SdS(N(sselfs_opensossO_CREATsO_RDONLYswaitsfcntlsflocksfiledescsLOCK_SHsLOCK_NBsTruesretsIOErrorsFalse(sselfswaitsret((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysdo_acquire_read_lock×s  cCsˆ|ititiBƒ| oKy'ti|iti ti Bƒt }Wnt j o t}nX|Snti|iti ƒt SdS(N(sselfs_opensossO_CREATsO_WRONLYswaitsfcntlsflocksfiledescsLOCK_EXsLOCK_NBsTruesretsIOErrorsFalse(sselfswaitsret((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysdo_acquire_write_lockçs  cCs|iƒdS(N(sselfsrelease_all_locks(sself((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysdo_release_read_locköscCs|iƒdS(N(sselfsrelease_all_locks(sself((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysdo_release_write_lockùscCsA|io3ti|itiƒti|iƒt|_ndS(N( sselfsopenedsfcntlsflocksfiledescsLOCK_UNsossclosesFalse(sself((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysrelease_all_locksüs cCsKti|itiƒo.yti|iƒWqGtj oqGXndS(N(sossaccesssselfsfilenamesF_OKsremovesOSError(sself((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys__del__s ( s__name__s __module__s__doc__s__init__s_opensdo_acquire_read_locksdo_acquire_write_locksdo_release_read_locksdo_release_write_locksrelease_all_lockss__del__(((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysFileSynchronizerºs       sConditionSynchronizercBsPtZdZd„Zed„ƒZed„Zd„Zed„Z d„Z RS(s‰a synchronizer using a Condition. this synchronizer is based on threading.Lock() objects and therefore must be shared among threads.cCsCtdd„ƒ|_d|_t|_titiƒƒ|_ dS(NscreatorcCstƒS(N(s SyncState(((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pyssi( s ThreadLocalsselfs tlocalstatesasyncsNonescurrent_sync_operations _threadings ConditionsLocks condition(sselfs identifier((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys__init__s  cCs |iƒS(N(sselfs tlocalstate(sself((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysscCs’|iiƒ|o)xK|itj o|iiƒqWn&|itj o|iiƒtSn|id7_|iiƒ| ot SndS(Ni( sselfs conditionsacquireswaitscurrent_sync_operationsNonesreleasesFalsesasyncsTrue(sselfswait((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysdo_acquire_read_locks   cCs||iiƒ|id8_|idjo%|itj o|iiƒqkn|idjo d‚n|iiƒdS(Niis7Synchronizer error - too many release_read_locks called(sselfs conditionsacquiresasyncscurrent_sync_operationsNones notifyAllsrelease(sself((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysdo_release_read_lock1s  cCsØ|iiƒ|o)xK|itj o|iiƒqWn&|itj o|iiƒtSnti ƒ|_|i djo6|o|iiƒq·t|_|iiƒtSn|iiƒ| ot SndS(Ni( sselfs conditionsacquireswaitscurrent_sync_operationsNonesreleasesFalses _threadings currentThreadsasyncsTrue(sselfswait((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysdo_acquire_write_lockCs$     cCsT|iiƒ|itiƒjo d‚nt|_|iiƒ|iiƒdS(Ns>Synchronizer error - current thread doesnt have the write lock( sselfs conditionsacquirescurrent_sync_operations _threadings currentThreadsNones notifyAllsrelease(sself((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysdo_release_write_lockhs     ( s__name__s __module__s__doc__s__init__spropertysstatesTruesdo_acquire_read_locksdo_release_read_locksdo_acquire_write_locksdo_release_write_lock(((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pysConditionSynchronizer s     %(s__all__sossweakrefstempfilesressyssutilsthreads_threads threadings _threadings ImportErrors dummy_threadsdummy_threadingsgetwindowsversionsFalses has_flocksfcntlsTruesNameLocksWeakValuedRegistrys synchronizerssNones Synchronizers SyncStatesobjectsSynchronizerImplsFileSynchronizersConditionSynchronizer(s has_flocksFileSynchronizers Synchronizers_threads__all__stempfiles synchronizerssresfcntlsSynchronizerImplsNameLockssyss SyncStates _threadingsConditionSynchronizersweakrefsos((s?build/bdist.darwin-8.0.1-x86/egg/myghtyutils/synchronization.pys? s0-       & %BQPK—tö4Yàsµ#µ#myghtyutils/session.py# $Id: session.py 2041 2006-02-05 19:02:14Z zzzeek $ # session.py - session management for Myghty # Copyright (C) 2004, 2005 Michael Bayer mike_mp@zzzcomputing.com # # This module is part of Myghty and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php # # import Cookie import hmac, md5, time, random, os, re, UserDict, datetime from container import * from util import * __all__ = ['SignedCookie', 'Session', 'MyghtySessionArgs'] class SignedCookie(Cookie.BaseCookie): "extends python cookie to give digital signature support" def __init__(self, secret, input=None): self.secret = secret Cookie.BaseCookie.__init__(self, input) def value_decode(self, val): sig = val[0:32] value = val[32:] if hmac.new(self.secret, value).hexdigest() != sig: return None, val return val[32:], val def value_encode(self, val): return val, ("%s%s" % (hmac.new(self.secret, val).hexdigest(), val)) class Session(UserDict.DictMixin): "session object that uses container package for storage" def __init__(self, request, id = None, invalidate_corrupt = False, use_cookies = True, type = None, data_dir = None, key = 'myghty_session_id', timeout = None, cookie_expires=True, secret = None, log_file = None, namespace_class = None, **params): if type is None: if data_dir is None: self.type = 'memory' else: self.type = 'file' else: self.type = type if namespace_class is None: self.namespace_class = container_registry(self.type, 'NamespaceManager') else: self.namespace_class = namespace_class self.params = params self.request = request self.data_dir = data_dir self.key = key self.timeout = timeout self.use_cookies = use_cookies self.cookie_expires = cookie_expires self.log_file = log_file self.was_invalidated = False self.secret = secret self.id = id if self.use_cookies: try: cookieheader = request.headers_in['cookie'] except KeyError: cookieheader = '' if secret is not None: try: self.cookie = SignedCookie(secret, input = cookieheader) except Cookie.CookieError: self.cookie = SignedCookie(secret, input = None) else: self.cookie = Cookie.SimpleCookie(input = cookieheader) if self.id is None and self.cookie.has_key(self.key): self.id = self.cookie[self.key].value if self.id is None: self._create_id() else: self.is_new = False try: self.load() except: if invalidate_corrupt: self.invalidate() else: raise def _create_id(self): self.id = md5.new( md5.new("%f%s%f%d" % (time.time(), id({}), random.random(), os.getpid()) ).hexdigest(), ).hexdigest() self.is_new = True if self.use_cookies: self.cookie[self.key] = self.id self.cookie[self.key]['path'] = '/' if self.cookie_expires is not True: if self.cookie_expires is False: expires = datetime.datetime.fromtimestamp( 0x7FFFFFFF ) elif isinstance(self.cookie_expires, datetime.timedelta): expires = datetime.datetime.today() + self.cookie_expires elif isinstance(self.cookie_expires, datetime.datetime): expires = self.cookie_expires else: raise ValueError("Invalid argument for cookie_expires: %s" % repr(self.cookie_expires)) self.cookie[self.key]['expires'] = expires.strftime("%a, %d-%b-%Y %H:%M:%S GMT" ) self.request.headers_out.add('set-cookie', self.cookie[self.key].output(header='')) created = property(lambda self: self.dict['_creation_time']) def delete(self): """deletes the persistent storage for this session, but remains valid. """ self.namespace.acquire_write_lock() try: for k in self.namespace.keys(): if not re.match(r'_creation_time|_accessed_time', k): del self.namespace[k] self.namespace['_accessed_time'] = time.time() finally: self.namespace.release_write_lock() def __getitem__(self, key): return self.dict.__getitem__(key) def __setitem__(self, key, value): self.dict.__setitem__(key, value) def __delitem__(self, key): del self.dict[key] def keys(self): return self.dict.keys() def __contains__(self, key): return self.dict.has_key(key) def has_key(self, key): return self.dict.has_key(key) def __iter__(self): return iter(self.dict.keys()) def iteritems(self): return self.dict.iteritems() def invalidate(self): "invalidates this session, creates a new session id, returns to the is_new state" namespace = self.namespace namespace.acquire_write_lock() try: namespace.remove() finally: namespace.release_write_lock() self.was_invalidated = True self._create_id() self.load() def load(self): "loads the data from this session from persistent storage" self.namespace = self.namespace_class(NamespaceContext(log_file = self.log_file), self.id, data_dir = self.data_dir, digest_filenames = False, **self.params) namespace = self.namespace namespace.acquire_write_lock() try: self.debug("session loading keys") self.dict = {} now = time.time() if not namespace.has_key('_creation_time'): namespace['_creation_time'] = now try: self.accessed = namespace['_accessed_time'] namespace['_accessed_time'] = now except KeyError: namespace['_accessed_time'] = self.accessed = now if self.timeout is not None and now - self.accessed > self.timeout: self.invalidate() else: for k in namespace.keys(): self.dict[k] = namespace[k] finally: namespace.release_write_lock() def save(self): "saves the data for this session to persistent storage" self.namespace.acquire_write_lock() try: self.debug("session saving keys") todel = [] for k in self.namespace.keys(): if not self.dict.has_key(k): todel.append(k) for k in todel: del self.namespace[k] for k in self.dict.keys(): self.namespace[k] = self.dict[k] self.namespace['_accessed_time'] = time.time() finally: self.namespace.release_write_lock() def lock(self): """locks this session against other processes/threads. this is automatic when load/save is called. ***use with caution*** and always with a corresponding 'unlock' inside a "finally:" block, as a stray lock typically cannot be unlocked without shutting down the whole application. """ self.namespace.acquire_write_lock() def unlock(self): """unlocks this session against other processes/threads. this is automatic when load/save is called. ***use with caution*** and always within a "finally:" block, as a stray lock typically cannot be unlocked without shutting down the whole application. """ self.namespace.release_write_lock() def debug(self, message): if self.log_file is not None: self.log_file.write(message) class MyghtySessionArgs(PrefixArgs): def __init__(self, data_dir = None, **params): PrefixArgs.__init__(self, 'session_') self.set_prefix_params(**params) if not self.params.has_key('data_dir') and data_dir is not None: self.params['data_dir'] = os.path.join(data_dir, 'sessions') def get_session(self, request, **params): return Session(request, **self.get_params(**params)) def clone(self, **params): p = self.get_params(**params) arg = MyghtySessionArgs() arg.params = p return arg PK–žC8°÷—^p^pmyghtyutils/util.pyc;ò >pÂDc@s dddddddddd d d d d ddgZydkZdkZWn%ej odkZdkZnXdkZdk Z dk Z dk Z dk Z dk Z dkZdkZdkZdkZdkZdkZdkZd„Zd„Zd„Zd„Zd efd„ƒYZdfd„ƒYZdfd„ƒYZde ifd„ƒYZde ifd„ƒYZdfd„ƒYZ dfd„ƒYZ!dfd„ƒYZ"de"fd„ƒYZ#de"fd„ƒYZ$de"fd„ƒYZ%d fd „ƒYZ&dS(!s OrderedDicts ThreadLocalsValues InheritedDictsConstructorClonesRegistrysWeakValuedRegistrysSyncDictsLRUCachesargdicts EncodedPathspids thread_idsverify_directorys PrefixArgssmoduleNcCstiƒSdS(N(s_threads get_ident(((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys thread_idscCstiƒSdS(N(sossgetpid(((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pyspidscCsed}xXti|tiƒ o@y|d7}ti|dƒWq |djo‚q\q Xq WdS(scverifies and creates a directory. tries to ignore collisions with other threads and processes.iiièiN(striessossaccesssdirsF_OKsmakedirs(sdirstries((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pysverify_directorys  cCsGt|ƒ}|idƒ}x!|dD]}t||ƒ}q&W|SdS(s5imports a module, in the ordinary way, by string names.iN(s __import__snamesmodssplits componentsscompsgetattr(snames componentsscompsmod((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pysmodule+s  cBstZdZd„ZRS(sasupports the argument constructor form of dict which doesnt seem to be present in python 2.2cKsti|ƒ|i|ƒdS(N(sdicts__init__sselfsupdatesparams(sselfsparams((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys__init__8s (s__name__s __module__s__doc__s__init__(((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pysargdict5s cBs5tZdZed„Zd„Zd„Zd„ZRS(s#allows pass-by-reference operationscCs ||_dS(N(svaluesself(sselfsvalue((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys__init__@scGs-t|ƒo|i|dƒn|iSdS(Ni(slensargsselfsassignsvalue(sselfsarg((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys__call__Bs cCst|iƒSdS(N(sstrsselfsvalue(sself((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys__str__HscCs ||_dS(N(svaluesself(sselfsvalue((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pysassignKs(s__name__s __module__s__doc__sNones__init__s__call__s__str__sassign(((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pysValue>s    cBs_tZdZeeed„Zd„Zd„Zd„Zd„Zd„Z d„Z d„Z RS( s$stores a value on a per-thread basiscCs7h|_||_||_|o|i|ƒndS(N(sselfsdictsdefaultscreatorsvaluesput(sselfsvaluesdefaultscreator((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys__init__Qs    cGs0t|ƒo|i|dƒn |iƒSdS(Ni(slensargsselfsputsget(sselfsarg((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys__call__Xs cCst|iƒƒSdS(N(sstrsselfsget(sself((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys__str__^scCs||itiƒ‡s(smapsselfslist(sself((sselfs4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pysvalues†scCst|iƒSdS(N(sitersselfslist(sself((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys__iter__‰scCs6tgi}|iD]}|||ƒq~ƒSdS(N(sitersappends_[1]sselfslistskey(sselfs_[1]skey((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys itervaluesŒscCs|iƒSdS(N(sselfs__iter__(sself((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pysiterkeysscCs?tgi}|iƒD]}||||fƒq~ƒSdS(N(sitersappends_[1]sselfskeysskey(sselfs_[1]skey((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys iteritems‘scCs$|i|=|i|ii|ƒ=dS(N(sselfsdictskeyslistsindex(sselfskey((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys __delitem__”s cCs<|i|ƒ o|ii|ƒn|ii||ƒdS(N(sselfshas_keyskeyslistsappendsdicts __setitem__sobject(sselfskeysobject((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys __setitem__˜scCs|ii|ƒSdS(N(sselfsdicts __getitem__skey(sselfskey((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys __getitem__žs(s__name__s __module__s__doc__sNones__init__skeyssupdatesvaluess__iter__s itervaluessiterkeyss iteritemss __delitem__s __setitem__s __getitem__(((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys OrderedDictvs           cBs\tZdZd„Zeed„Zd„Zd„Zd„Zd„Z d„Z d„Z RS( s_a dictionary that can defer lookups to a second dictionary if the key is not found locally.cCs||_||_dS(N(sdictsselfs superfunc(sselfsdicts superfunc((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys__init__¥s cCsu|tjo |tjo |iSnM|tjo/y|i|ƒSWqqtj o tSqqXn|i||ƒdS(N(skeysNonesvaluesselfsdicts __getitem__sKeyErrors __setitem__(sselfskeysvalue((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys__call__©s   cCsZ|i}|i|ƒo ||Sn&|iƒ}|tj o ||Snt|ƒ‚dS(N(sselfsdictshas_keyskeys superfuncsparentsNonesKeyError(sselfskeysparentsdict((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys __getitem__´s     cCs||i|' and stores a reference. cCs%||_h|_t|ƒ|_dS(N(sprefixsselfsparamsslensprelen(sselfsprefix((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys__init__"s  cKsSxL|iƒD]>\}}|d|i!|ijo||i||i" to this one.iN(sparamss iteritemsskeysitemsselfsprelensprefix(sselfsparamssitemskey((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pysset_prefix_params(s  cKs|ii|ƒdS(s=from the given dictionary, copies all key/values to this one.N(sselfsparamssupdate(sselfsparams((s4build/bdist.darwin-8.0.1-x86/egg/myghtyutils/util.pys set_params/scKsm|iiƒ}xS|iƒD]E\}}|d|i!|ijo||||ipÂDc@sºdkZdkZdkZdkZdkZdkZdkZdkZdkZdk Tdk TdddgZ dei fd„ƒYZ deifd„ƒYZdefd„ƒYZdS(N(s*s SignedCookiesSessionsMyghtySessionArgscBs,tZdZed„Zd„Zd„ZRS(s7extends python cookie to give digital signature supportcCs ||_tii||ƒdS(N(ssecretsselfsCookies BaseCookies__init__sinput(sselfssecretsinput((s7build/bdist.darwin-8.0.1-x86/egg/myghtyutils/session.pys__init__s cCsY|dd!}|d}ti|i|ƒiƒ|jot|fSn|d|fSdS(Nii ( svalssigsvalueshmacsnewsselfssecrets hexdigestsNone(sselfsvalsvaluessig((s7build/bdist.darwin-8.0.1-x86/egg/myghtyutils/session.pys value_decodes   "cCs-|dti|i|ƒiƒ|ffSdS(Ns%s%s(svalshmacsnewsselfssecrets hexdigest(sselfsval((s7build/bdist.darwin-8.0.1-x86/egg/myghtyutils/session.pys value_encode s(s__name__s __module__s__doc__sNones__init__s value_decodes value_encode(((s7build/bdist.darwin-8.0.1-x86/egg/myghtyutils/session.pys SignedCookies   c Bs×tZdZeeeeedeeeeed„ Zd„Zed„ƒZ d„Z d„Z d„Z d„Z d „Zd „Zd „Zd „Zd „Zd„Zd„Zd„Zd„Zd„Zd„ZRS(s6session object that uses container package for storagesmyghty_session_idc Ks|tjo'|tjo d|_q=d|_n ||_| tjot|idƒ|_n | |_| |_||_||_||_||_ ||_ | |_ | |_ t |_| |_||_|i oÞy|id}Wntj o d}nX| tj oKyt| d|ƒ|_Wqstij ot| dtƒ|_qsXntid|ƒ|_|itjo|ii|iƒo|i|ii|_q·n|itjo|iƒn t |_y|iƒWn|o|iƒq‚nXdS(NsmemorysfilesNamespaceManagerscookiessinput( stypesNonesdata_dirsselfsnamespace_classscontainer_registrysparamssrequestskeystimeouts use_cookiesscookie_expiresslog_filesFalseswas_invalidatedssecretsids headers_ins cookieheadersKeyErrors SignedCookiescookiesCookies CookieErrors SimpleCookieshas_keysvalues _create_idsis_newsloadsinvalidate_corrupts invalidate(sselfsrequestsidsinvalidate_corrupts use_cookiesstypesdata_dirskeystimeoutscookie_expiresssecretslog_filesnamespace_classsparamss cookieheader((s7build/bdist.darwin-8.0.1-x86/egg/myghtyutils/session.pys__init__'sR                     & cCs€titidtiƒthƒtiƒtiƒfƒiƒƒiƒ|_t |_ |i o|i|i |i wscCsu|iiƒzSx9|iiƒD](}tid|ƒ o|i|=q q Wtiƒ|idpÂDc@sdS(N((((s8build/bdist.darwin-8.0.1-x86/egg/myghtyutils/__init__.pys?sPK–tö4myghtyutils/ext/__init__.pyPK•žC869ñLŒŒmyghtyutils/ext/__init__.pyc;ò Xs  myghtyutils/ext/memcached.pyimport memcache from myghtyutils.synchronization import * from myghtyutils.container import NamespaceManager, Container import sys class MemcachedNamespaceManager(NamespaceManager): def __init__(self, context, namespace, url, **params): NamespaceManager.__init__(self, context, namespace, **params) self.mc = memcache.Client([url], debug=0) # memcached does its own locking. override our own stuff def do_acquire_read_lock(self): pass def do_release_read_lock(self): pass def do_acquire_write_lock(self, wait = True): return True def do_release_write_lock(self): pass # override open/close to do nothing, keep memcache connection open as long # as possible def open(self, *args, **params):pass def close(self, *args, **params):pass def __getitem__(self, key): value = self.mc.get(self.namespace + "_" + key) if value is None: raise KeyError(key) return value def __contains__(self, key): return self.mc.get(self.namespace + "_" + key) is not None def has_key(self, key): return self.mc.get(self.namespace + "_" + key) is not None def __setitem__(self, key, value): keys = self.mc.get(self.namespace + ':keys') if keys is None: keys = {} keys[key] = True self.mc.set(self.namespace + ':keys', keys) self.mc.set(self.namespace + "_" + key, value) def __delitem__(self, key): keys = self.mc.get(self.namespace + ':keys') try: del keys[key] self.mc.delete(self.namespace + "_" + key) self.mc.set(self.namespace + ':keys', keys) except KeyError: raise def do_remove(self): pass def keys(self): keys = self.mc.get(self.namespace + ':keys') if keys is None: return [] else: return keys.keys() class MemcachedContainer(Container): def do_init(self, **params): self.funclock = None def do_create_namespace_manager(self, context, namespace, url, **params): return MemcachedNamespaceManager(context, namespace, url, **params) def lock_createfunc(self, wait = True): if self.funclock is None: self.funclock = Synchronizer(identifier = "memcachedcontainer/funclock/%s" % self.namespacemanager.namespace, use_files = True, lock_dir = self.namespacemanager.lock_dir) return self.funclock.acquire_write_lock(wait) def unlock_createfunc(self): self.funclock.release_write_lock() PK–žC8•(¼ž..myghtyutils/ext/memcached.pyc;ò Xs  ¤½myghtyutils/ext/memcached.pyPK–žC8•(¼ž..¤RÇmyghtyutils/ext/memcached.pycPK»»ß