Skip to content
Permalink
Browse files

Handle deprecations in asyncio (#3509)

* passing loop to certain things was deprecated. additionally, `asyncio.get_event_loop()` is being deprecated

* awesome, checks are functioning as intended

* fun with fixtures

* we can just stop misuing that anyhow

* Update redbot/pytest/downloader.py

Co-Authored-By: jack1142 <6032823+jack1142@users.noreply.github.com>

Co-authored-by: jack1142 <6032823+jack1142@users.noreply.github.com>
  • Loading branch information
mikeshardmind and jack1142 committed Feb 5, 2020
1 parent 61ed864 commit 00cf3954838aee22a4e59355902f9314efb0b8f4
@@ -1,7 +1,5 @@
#!/usr/bin/env python

# Discord Version check

import asyncio
import functools
import getpass
@@ -20,7 +18,7 @@

import discord

# Set the event loop policies here so any subsequent `get_event_loop()`
# Set the event loop policies here so any subsequent `new_event_loop()`
# calls, in particular those as a result of the following imports,
# return the correct loop object.
from redbot import _update_event_loop_policy, __version__
@@ -298,7 +296,8 @@ def handle_edit(cli_flags: Namespace):
"""
This one exists to not log all the things like it's a full run of the bot.
"""
loop = asyncio.get_event_loop()
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
data_manager.load_basic_configuration(cli_flags.instance_name)
red = Red(cli_flags=cli_flags, description="Red V3", dm_help=None, fetch_offline_members=True)
try:
@@ -310,6 +309,7 @@ def handle_edit(cli_flags: Namespace):
print("Aborted!")
finally:
loop.run_until_complete(asyncio.sleep(1))
asyncio.set_event_loop(None)
loop.stop()
loop.close()
sys.exit(0)
@@ -460,7 +460,8 @@ def main():
handle_edit(cli_flags)
return
try:
loop = asyncio.get_event_loop()
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

if cli_flags.no_instance:
print(
@@ -524,6 +525,7 @@ def main():
# results in a resource warning instead
log.info("Please wait, cleaning up a bit more")
loop.run_until_complete(asyncio.sleep(2))
asyncio.set_event_loop(None)
loop.stop()
loop.close()
exit_code = red._shutdown_mode if red is not None else 1
@@ -462,7 +462,7 @@ def _done_callback(task: asyncio.Task) -> None:
if not deps:
await ctx.send_help()
return
repo = Repo("", "", "", "", Path.cwd(), loop=ctx.bot.loop)
repo = Repo("", "", "", "", Path.cwd())
async with ctx.typing():
success = await repo.install_raw_requirements(deps, self.LIB_PATH)

@@ -135,7 +135,6 @@ def __init__(
commit: str,
folder_path: Path,
available_modules: Tuple[Installable, ...] = (),
loop: Optional[asyncio.AbstractEventLoop] = None,
):
self.url = url
self.branch = branch
@@ -154,8 +153,6 @@ def __init__(

self._repo_lock = asyncio.Lock()

self._loop = loop if loop is not None else asyncio.get_event_loop()

@property
def clean_url(self) -> str:
"""Sanitized repo URL (with removed HTTP Basic Auth)"""
@@ -529,7 +526,7 @@ def _update_available_modules(self) -> Tuple[Installable, ...]:
env["LANGUAGE"] = "C"
kwargs["env"] = env
async with self._repo_lock:
p: CompletedProcess = await self._loop.run_in_executor(
p: CompletedProcess = await asyncio.get_running_loop().run_in_executor(
self._executor,
functools.partial(sp_run, *args, stdout=PIPE, stderr=PIPE, **kwargs),
)
@@ -1,4 +1,5 @@
import asyncio
import warnings
from asyncio import AbstractEventLoop, as_completed, Semaphore
from asyncio.futures import isfuture
from itertools import chain
@@ -177,14 +178,20 @@ def bounded_gather_iter(
TypeError
When invalid parameters are passed
"""
if loop is None:
loop = asyncio.get_event_loop()
if loop is not None:
warnings.warn(
"Explicitly passing the loop will not work in Red 3.4+ and is currently ignored."
"Call this from the related event loop.",
DeprecationWarning,
)

loop = asyncio.get_running_loop()

if semaphore is None:
if not isinstance(limit, int) or limit <= 0:
raise TypeError("limit must be an int > 0")

semaphore = Semaphore(limit, loop=loop)
semaphore = Semaphore(limit)

pending = []

@@ -195,7 +202,7 @@ def bounded_gather_iter(
cof = _sem_wrapper(semaphore, cof)
pending.append(cof)

return as_completed(pending, loop=loop)
return as_completed(pending)


def bounded_gather(
@@ -228,15 +235,21 @@ def bounded_gather(
TypeError
When invalid parameters are passed
"""
if loop is None:
loop = asyncio.get_event_loop()
if loop is not None:
warnings.warn(
"Explicitly passing the loop will not work in Red 3.4+ and is currently ignored."
"Call this from the related event loop.",
DeprecationWarning,
)

loop = asyncio.get_running_loop()

if semaphore is None:
if not isinstance(limit, int) or limit <= 0:
raise TypeError("limit must be an int > 0")

semaphore = Semaphore(limit, loop=loop)
semaphore = Semaphore(limit)

tasks = (_sem_wrapper(semaphore, task) for task in coros_or_futures)

return asyncio.gather(*tasks, loop=loop, return_exceptions=return_exceptions)
return asyncio.gather(*tasks, return_exceptions=return_exceptions)
@@ -5,6 +5,7 @@
import asyncio
import contextlib
import functools
import warnings
from typing import Union, Iterable, Optional
import discord

@@ -200,7 +201,9 @@ def start_adding_reactions(
await message.add_reaction(emoji)

if loop is None:
loop = asyncio.get_event_loop()
loop = asyncio.get_running_loop()
else:
warnings.warn("Explicitly passing the loop will not work in Red 3.4+", DeprecationWarning)

return loop.create_task(task())

@@ -76,7 +76,6 @@ def bot_repo(event_loop):
commit="",
url="https://empty.com/something.git",
folder_path=cwd,
loop=event_loop,
)


@@ -163,14 +162,7 @@ def _init_test_repo(destination: Path):
async def _session_git_repo(tmp_path_factory, event_loop):
# we will import repo only once once per session and duplicate the repo folder
repo_path = tmp_path_factory.mktemp("session_git_repo")
repo = Repo(
name="redbot-testrepo",
url="",
branch="master",
commit="",
folder_path=repo_path,
loop=event_loop,
)
repo = Repo(name="redbot-testrepo", url="", branch="master", commit="", folder_path=repo_path)
git_dirparams = _init_test_repo(repo_path)
fast_import = sp.Popen((*git_dirparams, "fast-import", "--quiet"), stdin=sp.PIPE)
with TEST_REPO_EXPORT_PTH.open(mode="rb") as f:
@@ -193,7 +185,6 @@ def _init_test_repo(destination: Path):
branch=_session_git_repo.branch,
commit=_session_git_repo.commit,
folder_path=repo_path,
loop=event_loop,
)
return repo

@@ -208,7 +199,6 @@ def _init_test_repo(destination: Path):
branch=_session_git_repo.branch,
commit=_session_git_repo.commit,
folder_path=repo_path,
loop=event_loop,
)
sp.run(("git", "clone", str(_session_git_repo.folder_path), str(repo_path)), check=True)
return repo
@@ -224,7 +214,6 @@ def _init_test_repo(destination: Path):
branch=git_repo.branch,
commit=git_repo.commit,
folder_path=repo_path,
loop=event_loop,
)
sp.run(("git", "clone", str(git_repo.folder_path), str(repo_path)), check=True)
return repo
@@ -371,8 +371,7 @@ def delete(
remove_datapath: Optional[bool],
):
"""Removes an instance."""
loop = asyncio.get_event_loop()
loop.run_until_complete(
asyncio.run(
remove_instance(
instance, interactive, delete_data, _create_backup, drop_db, remove_datapath
)
@@ -391,14 +390,12 @@ def convert(instance, backend):
default_dirs = deepcopy(data_manager.basic_config_default)
default_dirs["DATA_PATH"] = str(Path(instance_data[instance]["DATA_PATH"]))

loop = asyncio.get_event_loop()

if current_backend == BackendType.MONGOV1:
raise RuntimeError("Please see the 3.2 release notes for upgrading a bot using mongo.")
elif current_backend == BackendType.POSTGRES: # TODO: GH-3115
raise RuntimeError("Converting away from postgres isn't currently supported")
else:
new_storage_details = loop.run_until_complete(do_migration(current_backend, target))
new_storage_details = asyncio.run(do_migration(current_backend, target))

if new_storage_details is not None:
default_dirs["STORAGE_TYPE"] = target.value
@@ -422,8 +419,7 @@ def convert(instance, backend):
)
def backup(instance: str, destination_folder: Union[str, Path]) -> None:
"""Backup instance's data."""
loop = asyncio.get_event_loop()
loop.run_until_complete(create_backup(instance, Path(destination_folder)))
asyncio.run(create_backup(instance, Path(destination_folder)))


def run_cli():
@@ -12,8 +12,10 @@
@pytest.fixture(scope="session")
def event_loop(request):
"""Create an instance of the default event loop for entire session."""
loop = asyncio.get_event_loop_policy().new_event_loop()
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
yield loop
asyncio.set_event_loop(None)
loop.close()


0 comments on commit 00cf395

Please sign in to comment.
You can’t perform that action at this time.