Repository: fsspec/filesystem_spec

Issue:
'asyncio.get_event_loop_policy' is deprecated and slated for removal in Python 3.16 when running with python 3.14
While doing some testing with 3.14.0b2 I noticed a new Deprecation warning:
`'asyncio.get_event_loop_policy' is deprecated and slated for removal in Python 3.16 when running with python 3.14`
coming from:
https://github.com/fsspec/filesystem_spec/blob/26f1ea75351e39a80b29b27bea792351f3e8da9f/fsspec/asyn.py#L125

Python 3.14.0b2
fsspec==2025.5.1


Discussion:
Some more information on this would be helpful - do we no longer need to select the policy at all?
Thanks for the response.

The 3.14 docs mentions that polices are deprecated
https://docs.python.org/3.14/library/asyncio-policy.html#asyncio.get_event_loop_policy
> Policies are deprecated and will be removed in Python 3.16. Users are encouraged to use the [asyncio.run()](https://docs.python.org/3.14/library/asyncio-runner.html#asyncio.run) function or the [asyncio.Runner](https://docs.python.org/3.14/library/asyncio-runner.html#asyncio.Runner) with loop_factory to use the desired loop implementation.

The "what's new page has some more information about migrating from deprecated API:
https://docs.python.org/3.14/whatsnew/3.14.html#deprecated

Looking through the git history here it looks like the policy selection for windows was added here:
https://github.com/fsspec/filesystem_spec/pull/658

and perhaps deleting the policy selection is an option (see https://github.com/fsspec/sshfs/issues/29).

Let me know if there's anything I can do to help although I am not at all familiar with fsspec (aside from using it, which has been great!) or asyncio.
The initial reported bug is here: https://github.com/aio-libs/aiohttp/issues/4536. It is marked as "completed", but I don't see where the resolution is. In any case, it's a very old issue, so I propose we attempt to simply remove this block of code and see if it creates a problem for anyone (the original reports were pretty niche around proxy settings). 



Patch:
diff --git a/fsspec/asyn.py b/fsspec/asyn.py
index a66487e03..632bfe0f6 100644
--- a/fsspec/asyn.py
+++ b/fsspec/asyn.py
@@ -7,7 +7,6 @@
 import os
 import re
 import threading
-from contextlib import contextmanager
 from glob import has_magic
 from typing import TYPE_CHECKING, Iterable
 
@@ -120,18 +119,6 @@ def wrapper(*args, **kwargs):
     return wrapper
 
 
-@contextmanager
-def _selector_policy():
-    original_policy = asyncio.get_event_loop_policy()
-    try:
-        if os.name == "nt" and hasattr(asyncio, "WindowsSelectorEventLoopPolicy"):
-            asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
-
-        yield
-    finally:
-        asyncio.set_event_loop_policy(original_policy)
-
-
 def get_loop():
     """Create or return the default fsspec IO loop
 
@@ -142,8 +129,7 @@ def get_loop():
             # repeat the check just in case the loop got filled between the
             # previous two calls from another thread
             if loop[0] is None:
-                with _selector_policy():
-                    loop[0] = asyncio.new_event_loop()
+                loop[0] = asyncio.new_event_loop()
                 th = threading.Thread(target=loop[0].run_forever, name="fsspecIO")
                 th.daemon = True
                 th.start()
diff --git a/fsspec/implementations/asyn_wrapper.py b/fsspec/implementations/asyn_wrapper.py
index f7e885b24..9d106a74c 100644
--- a/fsspec/implementations/asyn_wrapper.py
+++ b/fsspec/implementations/asyn_wrapper.py
@@ -82,7 +82,7 @@ def _wrap_all_sync_methods(self):
                 continue
 
             method = getattr(self.sync_fs, method_name)
-            if callable(method) and not asyncio.iscoroutinefunction(method):
+            if callable(method) and not inspect.iscoroutinefunction(method):
                 async_method = async_wrapper(method, obj=self)
                 setattr(self, f"_{method_name}", async_method)
 


Test patch:
diff --git a/fsspec/tests/test_async.py b/fsspec/tests/test_async.py
index 4282996ad..97759ba30 100644
--- a/fsspec/tests/test_async.py
+++ b/fsspec/tests/test_async.py
@@ -1,7 +1,6 @@
 import asyncio
 import inspect
 import io
-import os
 import time
 
 import pytest
@@ -131,25 +130,6 @@ async def main(**kwargs):
     assert sum(asyncio.run(main())) == 32  # override
 
 
-@pytest.mark.skipif(os.name != "nt", reason="only for windows")
-def test_windows_policy():
-    from asyncio.windows_events import SelectorEventLoop
-
-    loop = fsspec.asyn.get_loop()
-    policy = asyncio.get_event_loop_policy()
-
-    # Ensure that the created loop always uses selector policy
-    assert isinstance(loop, SelectorEventLoop)
-
-    # Ensure that the global policy is not changed and it is
-    # set to the default one. This is important since the
-    # get_loop() method will temporarily override the policy
-    # with the one which uses selectors on windows, so this
-    # check ensures that we are restoring the old policy back
-    # after our change.
-    assert isinstance(policy, asyncio.DefaultEventLoopPolicy)
-
-
 def test_running_async():
     assert not fsspec.asyn.running_async()