1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import threading
from functools import wraps
threadlocal = threading.local()
class thread_local_router(object):
""" a decorator that wraps a function in a thread local definition block
useful for passing variables down the stack w/o.
Usage:
@thread_local(DB_FOR_READ_OVERRIDE='foobar')
def override(request):
...
"""
def __init__(self, **kwargs):
self.options = kwargs
def __enter__(self):
for attr, value in self.options.items():
setattr(threadlocal, attr, value)
def __exit__(self, exc_type, exc_value, traceback):
for attr in self.options.keys():
delattr(threadlocal, attr)
def __call__(self, func):
@wraps(func)
def inner(*args, **kwargs):
# the thread_local class is also a context manager
# which means it will call __enter__ and __exit__
with self:
return func(*args, **kwargs)
return inner