Skip to content

Commit aaded42

Browse files
authored
Merge pull request #671 from isidentical/fsspec-loop-ctx
asyn: introduce fsspec.asyn.fsspec_loop
2 parents 32eb908 + ad4b967 commit aaded42

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

docs/source/async.rst

+2
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,5 @@ available as the attribute ``.loop``.
127127
.. autofunction:: fsspec.asyn.sync_wrapper
128128

129129
.. autofunction:: fsspec.asyn.get_loop
130+
131+
.. autofunction:: fsspec.asyn.fsspec_loop

docs/source/changelog.rst

+2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ Changelog
44
Dev
55
---
66

7+
Enhancements
78

9+
- Introduce ``fsspec.asyn.fsspec_loop`` to temporarily switch to the fsspec loop. (#671)
810

911

1012
2021.06.0

fsspec/asyn.py

+30
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,17 @@ def _selector_policy():
105105
asyncio.set_event_loop_policy(original_policy)
106106

107107

108+
def get_running_loop():
109+
if hasattr(asyncio, "get_running_loop"):
110+
return asyncio.get_running_loop()
111+
else:
112+
loop = asyncio._get_running_loop()
113+
if loop is None:
114+
raise RuntimeError("no running event loop")
115+
else:
116+
return loop
117+
118+
108119
def get_loop():
109120
"""Create or return the default fsspec IO loop
110121
@@ -124,6 +135,25 @@ def get_loop():
124135
return loop[0]
125136

126137

138+
@contextmanager
139+
def fsspec_loop():
140+
"""Temporarily switch the current event loop to the fsspec's
141+
own loop, and then revert it back after the context gets
142+
terinated.
143+
"""
144+
try:
145+
original_loop = get_running_loop()
146+
except RuntimeError:
147+
original_loop = None
148+
149+
fsspec_loop = get_loop()
150+
try:
151+
asyncio._set_running_loop(fsspec_loop)
152+
yield fsspec_loop
153+
finally:
154+
asyncio._set_running_loop(original_loop)
155+
156+
127157
try:
128158
import resource
129159
except ImportError:

fsspec/tests/test_async.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import fsspec
1010
import fsspec.asyn
11-
from fsspec.asyn import _throttled_gather
11+
from fsspec.asyn import _throttled_gather, get_running_loop
1212

1313

1414
def test_sync_methods():
@@ -132,3 +132,23 @@ def test_windows_policy():
132132
# check ensures that we are restoring the old policy back
133133
# after our change.
134134
assert isinstance(policy, asyncio.DefaultEventLoopPolicy)
135+
136+
137+
def test_fsspec_loop():
138+
asyncio._set_running_loop(None)
139+
140+
with fsspec.asyn.fsspec_loop() as loop:
141+
assert get_running_loop() is loop
142+
assert get_running_loop() is fsspec.asyn.get_loop()
143+
144+
with pytest.raises(RuntimeError):
145+
get_running_loop()
146+
147+
original_loop = asyncio.new_event_loop()
148+
asyncio._set_running_loop(original_loop)
149+
150+
with fsspec.asyn.fsspec_loop() as loop:
151+
assert get_running_loop() is loop
152+
assert get_running_loop() is fsspec.asyn.get_loop()
153+
154+
assert get_running_loop() is original_loop

0 commit comments

Comments
 (0)