@@ -38,7 +38,7 @@ def __delattr__(self, key: str) -> None:
3838            raise  AttributeError (f"{ self !r} { key !r}  )
3939
4040
41- class  Local :
41+ def  Local ( thread_critical :  bool   =   False )  ->   threading . local   |   _CVar :
4242    """Local storage for async tasks. 
4343
4444    This is a namespace object (similar to `threading.local`) where data is 
@@ -65,65 +65,7 @@ class Local:
6565
6666    Unlike plain `contextvars` objects, this utility is threadsafe. 
6767    """ 
68- 
69-     def  __init__ (self , thread_critical : bool  =  False ) ->  None :
70-         self ._thread_critical  =  thread_critical 
71-         self ._thread_lock  =  threading .RLock ()
72- 
73-         self ._storage : "Union[threading.local, _CVar]" 
74- 
75-         if  thread_critical :
76-             # Thread-local storage 
77-             self ._storage  =  threading .local ()
78-         else :
79-             # Contextvar storage 
80-             self ._storage  =  _CVar ()
81- 
82-     @contextlib .contextmanager  
83-     def  _lock_storage (self ):
84-         # Thread safe access to storage 
85-         if  self ._thread_critical :
86-             try :
87-                 # this is a test for are we in a async or sync 
88-                 # thread - will raise RuntimeError if there is 
89-                 # no current loop 
90-                 asyncio .get_running_loop ()
91-             except  RuntimeError :
92-                 # We are in a sync thread, the storage is 
93-                 # just the plain thread local (i.e, "global within 
94-                 # this thread" - it doesn't matter where you are 
95-                 # in a call stack you see the same storage) 
96-                 yield  self ._storage 
97-             else :
98-                 # We are in an async thread - storage is still 
99-                 # local to this thread, but additionally should 
100-                 # behave like a context var (is only visible with 
101-                 # the same async call stack) 
102- 
103-                 # Ensure context exists in the current thread 
104-                 if  not  hasattr (self ._storage , "cvar" ):
105-                     self ._storage .cvar  =  _CVar ()
106- 
107-                 # self._storage is a thread local, so the members 
108-                 # can't be accessed in another thread (we don't 
109-                 # need any locks) 
110-                 yield  self ._storage .cvar 
111-         else :
112-             # Lock for thread_critical=False as other threads 
113-             # can access the exact same storage object 
114-             with  self ._thread_lock :
115-                 yield  self ._storage 
116- 
117-     def  __getattr__ (self , key ):
118-         with  self ._lock_storage () as  storage :
119-             return  getattr (storage , key )
120- 
121-     def  __setattr__ (self , key , value ):
122-         if  key  in  ("_local" , "_storage" , "_thread_critical" , "_thread_lock" ):
123-             return  super ().__setattr__ (key , value )
124-         with  self ._lock_storage () as  storage :
125-             setattr (storage , key , value )
126- 
127-     def  __delattr__ (self , key ):
128-         with  self ._lock_storage () as  storage :
129-             delattr (storage , key )
68+     if  thread_critical :
69+         return  threading .local ()
70+     else :
71+         return  _CVar ()
0 commit comments