@@ -38,7 +38,7 @@ def __delattr__(self, key: str) -> None:
38
38
raise AttributeError (f"{ self !r} object has no attribute { key !r} " )
39
39
40
40
41
- class Local :
41
+ def Local ( thread_critical : bool = False ) -> threading . local | _CVar :
42
42
"""Local storage for async tasks.
43
43
44
44
This is a namespace object (similar to `threading.local`) where data is
@@ -65,65 +65,7 @@ class Local:
65
65
66
66
Unlike plain `contextvars` objects, this utility is threadsafe.
67
67
"""
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