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 |