1010
1111_run_close_loop = True
1212
13- def apply (loop = None , * , run_close_loop : bool = False ):
14- """Patch asyncio to make its event loop reentrant."""
13+ class _NestAsyncio2 :
14+ '''Internal class of `nest_asyncio2`.
15+
16+ Mainly for holding the original properties to support unapply() and nest_asyncio2.run().
17+ '''
18+ pass
19+
20+ def apply (
21+ loop = None ,
22+ * ,
23+ run_close_loop : bool = False ,
24+ error_on_mispatched : bool = False ,
25+ ):
26+ '''Patch asyncio to make its event loop reentrant.
27+
28+ - `run_close_loop`: Close the event loop created by `asyncio.run()`, if any.
29+ See README for details.
30+ - `error_on_mispatched`:
31+ - `False` (default): Warn if asyncio is already patched by `nest_asyncio` on Python 3.12+.
32+ - `True`: Raise `RuntimeError` if asyncio is already patched by `nest_asyncio`.
33+ '''
1534 global _run_close_loop
1635
17- _patch_asyncio ()
36+ _patch_asyncio (error_on_mispatched = error_on_mispatched )
1837 _patch_policy ()
1938 _patch_tornado ()
2039
@@ -106,7 +125,7 @@ def run(main, *, debug=False, loop_factory=None):
106125 # Avoid ResourceWarning: unclosed event loop
107126 loop .close ()
108127
109- def _patch_asyncio ():
128+ def _patch_asyncio (* , error_on_mispatched : bool = False ):
110129 """Patch asyncio module to use pure Python tasks and futures."""
111130
112131 def _get_event_loop (stacklevel = 3 ):
@@ -117,6 +136,12 @@ def _get_event_loop(stacklevel=3):
117136
118137 # Use module level _current_tasks, all_tasks and patch run method.
119138 if hasattr (asyncio , '_nest_patched' ):
139+ if not hasattr (asyncio , '_nest_asyncio2' ):
140+ if error_on_mispatched :
141+ raise RuntimeError ('asyncio is already patched by nest_asyncio' )
142+ elif sys .version_info >= (3 , 12 , 0 ):
143+ import warnings
144+ warnings .warn ('asyncio is already patched by nest_asyncio. You may encounter bugs related to asyncio' )
120145 return
121146
122147 # Using _PyTask on Python 3.14+ will break current_task() (and all_tasks(),
@@ -138,6 +163,7 @@ def _get_event_loop(stacklevel=3):
138163 asyncio .get_event_loop = _get_event_loop
139164 asyncio .run = run
140165 asyncio ._nest_patched = True
166+ asyncio ._nest_asyncio2 = _NestAsyncio2 ()
141167
142168
143169def _patch_policy ():
@@ -310,6 +336,7 @@ def _check_running(self):
310336 curr_tasks = asyncio .tasks ._current_tasks \
311337 if sys .version_info >= (3 , 7 , 0 ) else asyncio .Task ._current_tasks
312338 cls ._nest_patched = True
339+ cls ._nest_asyncio2 = _NestAsyncio2 ()
313340
314341
315342def _patch_tornado ():
0 commit comments