Skip to content

Commit 8ead57f

Browse files
committed
feat: _nest_asyncio2 marker and error_on_mispatched (#1)
1 parent 0688a39 commit 8ead57f

File tree

4 files changed

+65
-5
lines changed

4 files changed

+65
-5
lines changed

nest_asyncio2.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,30 @@
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

143169
def _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

315342
def _patch_tornado():

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = nest-asyncio2
3-
version = 1.6.3
3+
version = 1.7.0
44
author = Ewald R. de Wit
55
author_email = [email protected]
66
license = BSD

tests/mispatched.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# /// script
2+
# requires-python = ">=3.5"
3+
# dependencies = [
4+
# "nest-asyncio",
5+
# "nest-asyncio2",
6+
# ]
7+
#
8+
# [tool.uv.sources]
9+
# nest-asyncio2 = { path = "../", editable = true }
10+
# ///
11+
import warnings
12+
import sys
13+
14+
import nest_asyncio
15+
nest_asyncio.apply()
16+
17+
import nest_asyncio2
18+
19+
with warnings.catch_warnings(record=True) as w:
20+
nest_asyncio2.apply()
21+
if sys.version_info < (3, 12, 0):
22+
assert len(w) == 0, w
23+
else:
24+
assert len(w) == 1, w
25+
26+
error = False
27+
try:
28+
nest_asyncio2.apply(error_on_mispatched=True)
29+
except RuntimeError:
30+
error = True
31+
assert error

tests/test.ps1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ function Test {
1818
}
1919
}
2020

21+
Test -V @("3.11", "3.12", "3.13", "3.14") -Py mispatched.py
22+
2123
# uv run --python 3.5 nest_test.py
2224
uv run --python 3.8 nest_test.py
2325
if (!$?) {

0 commit comments

Comments
 (0)