| OLD | NEW |
| (Empty) |
| 1 # -*- test-case-name: twisted.test.test_context -*- | |
| 2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
| 3 # See LICENSE for details. | |
| 4 | |
| 5 # | |
| 6 | |
| 7 """ | |
| 8 Dynamic pseudo-scoping for Python. | |
| 9 | |
| 10 Call functions with context.call({key: value}, func); func and | |
| 11 functions that it calls will be able to use 'context.get(key)' to | |
| 12 retrieve 'value'. | |
| 13 | |
| 14 This is thread-safe. | |
| 15 """ | |
| 16 | |
| 17 try: | |
| 18 from threading import local | |
| 19 except ImportError: | |
| 20 local = None | |
| 21 | |
| 22 from twisted.python import threadable | |
| 23 | |
| 24 defaultContextDict = {} | |
| 25 | |
| 26 setDefault = defaultContextDict.__setitem__ | |
| 27 | |
| 28 class ContextTracker: | |
| 29 def __init__(self): | |
| 30 self.contexts = [defaultContextDict] | |
| 31 | |
| 32 def callWithContext(self, ctx, func, *args, **kw): | |
| 33 newContext = self.contexts[-1].copy() | |
| 34 newContext.update(ctx) | |
| 35 self.contexts.append(newContext) | |
| 36 try: | |
| 37 return func(*args,**kw) | |
| 38 finally: | |
| 39 self.contexts.pop() | |
| 40 | |
| 41 def getContext(self, key, default=None): | |
| 42 return self.contexts[-1].get(key, default) | |
| 43 | |
| 44 | |
| 45 class _ThreadedContextTracker: | |
| 46 def __init__(self): | |
| 47 self.threadId = threadable.getThreadID | |
| 48 self.contextPerThread = {} | |
| 49 | |
| 50 def currentContext(self): | |
| 51 tkey = self.threadId() | |
| 52 try: | |
| 53 return self.contextPerThread[tkey] | |
| 54 except KeyError: | |
| 55 ct = self.contextPerThread[tkey] = ContextTracker() | |
| 56 return ct | |
| 57 | |
| 58 def callWithContext(self, ctx, func, *args, **kw): | |
| 59 return self.currentContext().callWithContext(ctx, func, *args, **kw) | |
| 60 | |
| 61 def getContext(self, key, default=None): | |
| 62 return self.currentContext().getContext(key, default) | |
| 63 | |
| 64 | |
| 65 class _TLSContextTracker(_ThreadedContextTracker): | |
| 66 def __init__(self): | |
| 67 self.storage = local() | |
| 68 | |
| 69 def currentContext(self): | |
| 70 try: | |
| 71 return self.storage.ct | |
| 72 except AttributeError: | |
| 73 ct = self.storage.ct = ContextTracker() | |
| 74 return ct | |
| 75 | |
| 76 if local is None: | |
| 77 ThreadedContextTracker = _ThreadedContextTracker | |
| 78 else: | |
| 79 ThreadedContextTracker = _TLSContextTracker | |
| 80 | |
| 81 def installContextTracker(ctr): | |
| 82 global theContextTracker | |
| 83 global call | |
| 84 global get | |
| 85 | |
| 86 theContextTracker = ctr | |
| 87 call = theContextTracker.callWithContext | |
| 88 get = theContextTracker.getContext | |
| 89 | |
| 90 installContextTracker(ThreadedContextTracker()) | |
| OLD | NEW |