Compare commits

...

13 Commits
3.3.0 ... 3.3.1

Author SHA1 Message Date
Michael H
c426aefd1a Version 3.3.1 (#3510)
* 331

* okay sphinx
2020-02-05 23:21:38 +01:00
Michael H
00cf395483 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>
2020-02-05 17:16:13 -05:00
Kowlin
61ed864e02 CI ports from Travis CI (#3435)
* Attempt 1, I suppose.

* Add the remaining 2 out of 3 jobs

* Spacing matters T_T

* So does formatting...

* More formatting fixing.

* First attempt at postgres services.

* Postgres attempt 2

* Update tests.yml

Flatten a python version I suppose.

* Update tests.yml

* Update tests.yml

* Update tests.yml

* Update tests.yml

* I wonder if this works lmao

* this is fun™

* let's go back

* add fail-fast

* Added publishing workflows

Co-authored-by: jack1142 <6032823+jack1142@users.noreply.github.com>
2020-02-05 16:02:05 -05:00
Lane Babuder
90b099395b Adding CentOS 8 Documentation (#3463)
IUS will not be supporting RHEL 8, so utilizing epel-release and telling the system to use standard git is the best option.
2020-02-03 16:57:09 -05:00
aikaterna
12e6f44135 [Core] No DMing the bot (#3478)
* [Core] No DMing the bot

* Return early if target user is a bot
2020-02-03 16:26:33 -05:00
PredaaA
e44fc69d14 [Core] Add a cli flag for setting a max size of message cache (#3474)
* Add an arg in cli to change message cache size

* Add an arg in cli to change message cache size

* Changelog

* Actually pass None in message_cache_size

* Update cli.py

* Add a cli arg to disable message cache.

* Add a cli arg to disable message cache.

* well go away you useless

* you actually are an int

* Check if message cache is higher than 0 when set it.

* Use sys.maxsize as max cache size.

* Update cli.py

* Add bot.max_messages property.

* typos

* 🤦

* style
2020-02-03 16:14:45 -05:00
jack1142
8454239a98 [Mod] Fix shorthelp for [p]modset dm (#3488)
* Update settings.py

* Update settings.py

* Create 3488.misc.rst

* Update settings.py
2020-02-03 16:14:19 -05:00
jack1142
64106c771a Allow to edit prefixes through redbot --edit (#3486)
* feat: allow to edit prefixes through `redbot --edit`

* enhance: allow to setup multiple prefixes

* fix: gotta break out of the loop

* fix: gotta sort prefixes in reversed order

* fix: editing prefix shouldn't save it as token

* fix: sort prefixes when using flag too

* chore(changelog): add towncrier entry

* docs: update help for `--edit` flag
2020-02-03 16:08:48 -05:00
jack1142
17234ac8fa Add -e flag to journalctl command in systemd guide so that it takes the user to the end of logs automatically. (#3483)
* Make journalctl's pager go to the end of logs automatically

* Aaaaaaaand changelog
2020-02-01 01:26:39 +01:00
Kowlin
b64802b92f Fix for the unknown days argument on hackban. (#3475) 2020-01-30 18:55:11 +01:00
jack1142
6fa02b1a8d [Docs] Trigger update on sudo add-apt-repository (#3464) 2020-01-27 18:41:57 -09:00
Michael H
7420df9598 let's fix this for dev testers (#3458) 2020-01-27 03:35:16 -05:00
Michael H
00bcd480e7 dev bump (#3455) 2020-01-26 20:39:38 -05:00
21 changed files with 303 additions and 59 deletions

1
.github/CODEOWNERS vendored
View File

@@ -62,3 +62,4 @@ redbot/setup.py @tekulvw
# Others
.travis.yml @Kowlin
crowdin.yml @Kowlin
.github/workflows/* @Kowlin

28
.github/workflows/publish_crowdin.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Publish to Crowdin
on:
push:
tags:
- "*"
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.8'
- name: Install dependencies
run: |
curl https://artifacts.crowdin.com/repo/GPG-KEY-crowdin | sudo apt-key add -
echo "deb https://artifacts.crowdin.com/repo/deb/ /" | sudo tee -a /etc/apt/sources.list
sudo apt-get update -qq
sudo apt-get install -y crowdin
pip install redgettext==3.1
- name: Publish
env:
CROWDIN_API_KEY: ${{ secrets.crowdin_token}}
CROWDIN_PROJECT_ID: ${{ secrets.crowdin_identifier }}
run: |
make upload_translations

26
.github/workflows/publish_pypi.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: Publish to PyPI
on:
push:
tags:
- "*"
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.8'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.pypi_token }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*

73
.github/workflows/tests.yml vendored Normal file
View File

@@ -0,0 +1,73 @@
name: Tests
on: [push, pull_request]
jobs:
tox:
runs-on: ubuntu-latest
strategy:
matrix:
python_version:
- "3.8"
tox_env:
- py
- style
- docs
include:
- tox_env: py
friendly_name: Tests
- tox_env: style
friendly_name: Style
- tox_env: docs
friendly_name: Docs
fail-fast: false
name: Tox - ${{ matrix.friendly_name }}
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python_version }}
- name: Install tox
run: |
python -m pip install --upgrade pip
pip install tox
- name: Tox test
env:
TOXENV: ${{ matrix.tox_env }}
run: tox
tox-postgres:
runs-on: ubuntu-latest
strategy:
matrix:
python_version:
- "3.8"
fail-fast: false
name: Tox - Postgres
services:
postgresql:
image: postgres:10
ports:
- 5432:5432
env:
POSTGRES_DB: red_db
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python_version }}
- name: Install tox
run: |
python -m pip install --upgrade pip
pip install tox
- name: Tox test
env:
TOXENV: postgres
PGDATABASE: red_db
PGUSER: postgres
PGPASSWORD: postgres
PGPORT: 5432
run: tox

View File

@@ -71,4 +71,4 @@ type the following command in the terminal, still by adding the instance name af
To view Reds log, you can acccess through journalctl:
:code:`sudo journalctl -u red@instancename`
:code:`sudo journalctl -eu red@instancename`

View File

@@ -1,5 +1,39 @@
.. 3.3.x Changelogs
Redbot 3.3.1 (2020-02-05)
=========================
Core Bot
--------
- Add a cli flag for setting a max size of message cache
- Allow to edit prefix from command line using ``redbot --edit``.
- Some functions have been changed to no longer use deprecated asyncio functions
Core Commands
-------------
- The short help text for dm has been made more useful
- dm no longer allows owners to have the bot attempt to DM itself
Utils
-----
- Passing the event loop explicitly in utils is deprecated (Removal in 3.4)
Mod Cog
-------
- Hackban now works properly without being provided a number of days
Documentation Changes
---------------------
- Add ``-e`` flag to ``journalctl`` command in systemd guide so that it takes the user to the end of logs automatically.
- Added section to install docs for CentOS 8
- Improve usage of apt update in docs
Redbot 3.3.0 (2020-01-26)
=========================

View File

@@ -67,6 +67,25 @@ Complete the rest of the installation by `installing Python 3.8 with pyenv <inst
----
.. _install-centos8:
.. _install-rhel8:
~~~~~~~~~~~~~~~~~
CentOS and RHEL 8
~~~~~~~~~~~~~~~~~
.. code-block:: none
yum -y install epel-release
yum update -y
yum -y groupinstall development
yum -y install git zlib-devel bzip2 bzip2-devel readline-devel sqlite \
sqlite-devel openssl-devel xz xz-devel libffi-devel findutils java-11-openjdk
Complete the rest of the installation by `installing Python 3.8 with pyenv <install-python-pyenv>`.
----
.. _install-debian-stretch:
~~~~~~~~~~~~~~
@@ -231,14 +250,14 @@ We recommend adding the ``git-core`` ppa to install Git 2.11 or greater:
.. code-block:: none
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository ppa:git-core/ppa
sudo apt -y install software-properties-common
sudo add-apt-repository -yu ppa:git-core/ppa
We recommend adding the ``deadsnakes`` ppa to install Python 3.8.1 or greater:
.. code-block:: none
sudo add-apt-repository ppa:deadsnakes/ppa
sudo add-apt-repository -yu ppa:deadsnakes/ppa
Now install the pre-requirements with apt:
@@ -262,8 +281,8 @@ We recommend adding the ``git-core`` ppa to install Git 2.11 or greater:
.. code-block:: none
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository ppa:git-core/ppa
sudo apt -y install software-properties-common
sudo add-apt-repository -yu ppa:git-core/ppa
Now, to install non-native version of python on non-LTS versions of Ubuntu, we recommend
installing pyenv. To do this, first run the following commands:

View File

@@ -191,7 +191,7 @@ def _update_event_loop_policy():
_asyncio.set_event_loop_policy(_uvloop.EventLoopPolicy())
__version__ = "3.3.0"
__version__ = "3.3.1"
version_info = VersionInfo.from_str(__version__)
# Filter fuzzywuzzy slow sequence matcher warning

View File

@@ -1,7 +1,5 @@
#!/usr/bin/env python
# Discord Version check
import asyncio
import functools
import getpass
@@ -20,7 +18,7 @@ from typing import NoReturn
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__
@@ -107,6 +105,7 @@ async def edit_instance(red, cli_flags):
no_prompt = cli_flags.no_prompt
token = cli_flags.token
owner = cli_flags.owner
prefix = cli_flags.prefix
old_name = cli_flags.instance_name
new_name = cli_flags.edit_instance_name
data_path = cli_flags.edit_data_path
@@ -119,14 +118,20 @@ async def edit_instance(red, cli_flags):
if new_name is None and confirm_overwrite:
print("--overwrite-existing-instance can't be used without --edit-instance-name argument")
sys.exit(1)
if no_prompt and all(to_change is None for to_change in (token, owner, new_name, data_path)):
if (
no_prompt
and all(to_change is None for to_change in (token, owner, new_name, data_path))
and not prefix
):
print(
"No arguments to edit were provided. Available arguments (check help for more "
"information): --edit-instance-name, --edit-data-path, --copy-data, --owner, --token"
"No arguments to edit were provided."
" Available arguments (check help for more information):"
" --edit-instance-name, --edit-data-path, --copy-data, --owner, --token, --prefix"
)
sys.exit(1)
await _edit_token(red, token, no_prompt)
await _edit_prefix(red, prefix, no_prompt)
await _edit_owner(red, owner, no_prompt)
data = deepcopy(data_manager.basic_config)
@@ -152,6 +157,26 @@ async def _edit_token(red, token, no_prompt):
print("Token updated.\n")
async def _edit_prefix(red, prefix, no_prompt):
if prefix:
prefixes = sorted(prefix, reverse=True)
await red._config.prefix.set(prefixes)
elif not no_prompt and confirm("Would you like to change instance's prefixes?", default=False):
print(
"Enter the prefixes, separated by a space (please note "
"that prefixes containing a space will need to be added with [p]set prefix)"
)
while True:
prefixes = input("> ").strip().split()
if not prefixes:
print("You need to pass at least one prefix!")
continue
prefixes = sorted(prefixes, reverse=True)
await red._config.prefix.set(prefixes)
print("Prefixes updated.\n")
break
async def _edit_owner(red, owner, no_prompt):
if owner:
if not (15 <= len(str(owner)) <= 21):
@@ -271,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:
@@ -283,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)
@@ -433,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(
@@ -497,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

View File

@@ -462,7 +462,7 @@ class Downloader(commands.Cog):
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)

View File

@@ -135,7 +135,6 @@ class Repo(RepoJSONMixin):
commit: str,
folder_path: Path,
available_modules: Tuple[Installable, ...] = (),
loop: Optional[asyncio.AbstractEventLoop] = None,
):
self.url = url
self.branch = branch
@@ -154,8 +153,6 @@ class Repo(RepoJSONMixin):
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 @@ class Repo(RepoJSONMixin):
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),
)

View File

@@ -308,6 +308,9 @@ class KickBanMixin(MixinMeta):
await ctx.send_help()
return
if days is None:
days = await self.settings.guild(guild).default_days()
if not (0 <= days <= 7):
await ctx.send(_("Invalid days. Must be between 0 and 7."))
return
@@ -329,9 +332,6 @@ class KickBanMixin(MixinMeta):
await show_results()
return
if days is None:
days = await self.settings.guild(guild).default_days()
for user_id in user_ids:
user = guild.get_member(user_id)
if user is not None:

View File

@@ -215,8 +215,7 @@ class ModSettings(MixinMeta):
@modset.command()
@commands.guild_only()
async def dm(self, ctx: commands.Context, enabled: bool = None):
"""Toggle whether to send a message to a user when they are
kicked/banned.
"""Toggle whether a message should be sent to a user when they are kicked/banned.
If this option is enabled, the bot will attempt to DM the user with the guild name
and reason as to why they were kicked/banned.

View File

@@ -149,6 +149,12 @@ class RedBase(
if "command_not_found" not in kwargs:
kwargs["command_not_found"] = "Command {} not found.\n{}"
message_cache_size = cli_flags.message_cache_size
if cli_flags.no_message_cache:
message_cache_size = None
kwargs["max_messages"] = message_cache_size
self._max_messages = message_cache_size
self._uptime = None
self._checked_time_accuracy = None
self._color = discord.Embed.Empty # This is needed or color ends up 0x000000
@@ -271,6 +277,10 @@ class RedBase(
def colour(self) -> NoReturn:
raise AttributeError("Please fetch the embed colour with `get_embed_colour`")
@property
def max_messages(self) -> Optional[int]:
return self._max_messages
async def allowed_by_whitelist_blacklist(
self,
who: Optional[Union[discord.Member, discord.User]] = None,

View File

@@ -74,6 +74,22 @@ async def interactive_config(red, token_set, prefix_set, *, print_header=True):
return token
def positive_int(arg: str) -> int:
try:
x = int(arg)
except ValueError:
raise argparse.ArgumentTypeError("Message cache size has to be a number.")
if x < 1000:
raise argparse.ArgumentTypeError(
"Message cache size has to be greater than or equal to 1000."
)
if x > sys.maxsize:
raise argparse.ArgumentTypeError(
f"Message cache size has to be lower than or equal to {sys.maxsize}."
)
return x
def parse_cli_flags(args):
parser = argparse.ArgumentParser(
description="Red - Discord Bot", usage="redbot <instance_name> [arguments]"
@@ -90,7 +106,7 @@ def parse_cli_flags(args):
action="store_true",
help="Edit the instance. This can be done without console interaction "
"by passing --no-prompt and arguments that you want to change (available arguments: "
"--edit-instance-name, --edit-data-path, --copy-data, --owner, --token).",
"--edit-instance-name, --edit-data-path, --copy-data, --owner, --token, --prefix).",
)
parser.add_argument(
"--edit-instance-name",
@@ -212,6 +228,15 @@ def parse_cli_flags(args):
"all of the data on the host machine."
),
)
parser.add_argument(
"--message-cache-size",
type=positive_int,
default=1000,
help="Set the maximum number of messages to store in the internal message cache.",
)
parser.add_argument(
"--no-message-cache", action="store_true", help="Disable the internal message cache.",
)
args = parser.parse_args(args)

View File

@@ -1581,12 +1581,12 @@ class Core(commands.Cog, CoreLogic):
settings, 'appearance' tab. Then right click a user
and copy their id"""
destination = discord.utils.get(ctx.bot.get_all_members(), id=user_id)
if destination is None:
if destination is None or destination.bot:
await ctx.send(
_(
"Invalid ID or user not found. You can only "
"send messages to people I share a server "
"with."
"Invalid ID, user not found, or user is a bot. "
"You can only send messages to people I share "
"a server with."
)
)
return

View File

@@ -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)

View File

@@ -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())

View File

@@ -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 @@ async def git_repo(_session_git_repo, tmp_path, event_loop):
branch=_session_git_repo.branch,
commit=_session_git_repo.commit,
folder_path=repo_path,
loop=event_loop,
)
return repo
@@ -208,7 +199,6 @@ async def cloned_git_repo(_session_git_repo, tmp_path, event_loop):
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 @@ async def git_repo_with_remote(git_repo, tmp_path, event_loop):
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

View File

@@ -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():

View File

@@ -12,8 +12,10 @@ _update_event_loop_policy()
@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()