1import threading 2 3 4class ClassProperty(property): 5 """ 6 Use a classmethod as a property 7 http://stackoverflow.com/a/1383402/1258307 8 """ 9 10 def __get__(self, cls, owner): 11 return self.fget.__get__(None, owner)() # pylint: disable=no-member 12 13 14class RequestContext: 15 """ 16 A context manager that saves some per-thread state globally. 17 Intended for use with Tornado's StackContext. 18 https://gist.github.com/simon-weber/7755289 19 Simply import this class into any module and access the current request handler by this 20 class's class method property 'current'. If it returns None, there's no active request. 21 .. code:: python 22 from raas.utils.ctx import RequestContext 23 current_request_handler = RequestContext.current 24 """ 25 26 _state = threading.local() 27 _state.current_request = {} 28 29 def __init__(self, current_request): 30 self._current_request = current_request 31 32 @ClassProperty 33 @classmethod 34 def current(cls): 35 if not hasattr(cls._state, "current_request"): 36 return {} 37 return cls._state.current_request 38 39 def __enter__(self): 40 self._prev_request = self.__class__.current 41 self.__class__._state.current_request = self._current_request 42 43 def __exit__(self, *exc): 44 self.__class__._state.current_request = self._prev_request 45 del self._prev_request 46 return False 47 48 def __call__(self): 49 return self 50