diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6751594..c148ddd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.7 + python-version: 3.13 - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 984be83..20a52bf 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: registry-gitlab.gog.com/docker/python:3.7.3 +image: registry-gitlab.gog.com/docker/python:3.13 stages: - test @@ -18,10 +18,10 @@ deploy_package: TWINE_USERNAME: $PYPI_USERNAME TWINE_PASSWORD: $PYPI_PASSWORD script: - - pip install twine wheel + - pip install twine wheel build - rm -rf dist - export VERSION=$(python setup.py --version) - - python setup.py sdist --formats=gztar bdist_wheel + - python -m build --sdist --wheel - twine upload dist/* - curl -X POST --silent --show-error --fail "https://gitlab.gog.com/api/v4/projects/${CI_PROJECT_ID}/repository/tags?tag_name=${VERSION}&ref=${CI_COMMIT_REF_NAME}&private_token=${PACKAGE_DEPLOYER_API_TOKEN}" diff --git a/README.md b/README.md index 9ed988b..8fffac6 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ if __name__ == "__main__": ## Deployment -The client has a built-in Python 3.7 interpreter, so integrations are delivered as Python modules. +The client has a built-in Python 3.13 interpreter, so integrations are delivered as Python modules. In order to be found by GOG Galaxy 2.0 an integration folder should be placed in [lookup directory](#deploy-location). Beside all the Python files, the integration folder must contain [manifest.json](#deploy-manifest) and all third-party dependencies. See an [exemplary structure](#deploy-structure-example). ### Lookup directory @@ -88,7 +88,7 @@ In order to be found by GOG Galaxy 2.0 an integration folder should be placed in `~/Library/Application Support/GOG.com/Galaxy/plugins/installed` ### Logging -Root logger is already setup by GOG Galaxy to store rotated log files in: +Root logger is already setup by GOG Galaxy to store rotated log files in: - Windows: @@ -128,9 +128,9 @@ Obligatory JSON file to be placed in an integration folder. ### Dependencies -All third-party packages (packages not included in the Python 3.7 standard library) should be deployed along with plugin files. Use the following command structure: +All third-party packages (packages not included in the Python 3.13 standard library) should be deployed along with plugin files. Use the following command structure: -```pip install DEP --target DIR --implementation cp --python-version 37``` +```pip install DEP --target DIR --implementation cp --python-version 313``` For example, a plugin that uses *requests* could have the following structure: diff --git a/requirements-dev.txt b/requirements-dev.txt index 018ae17..106c99b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,7 +1,8 @@ -r requirements.txt -pytest==5.2.2 -pytest-asyncio==0.10.0 -pytest-mock==1.10.3 -pytest-mypy==0.4.1 -pytest-flakes==4.0.0 -types-certifi==2020.4.0 +pytest==8.4.1 +pytest-asyncio==1.1.0 +pytest-mock==3.14.1 +pytest-mypy==1.0.1 +pytest-flakes==4.0.5 +types-certifi==2021.10.8.3 +setuptools==80.9.0 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index d82a81f..e3c75c9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ -e . # Copied from setup.py because of a pip bug # see https://github.com/pypa/pip/issues/4780 -aiohttp==3.5.4 -certifi==2019.3.9 +aiohttp==3.12.15 +certifi==2025.8.3 psutil==5.6.6; sys_platform == 'darwin' # End of copy from setup.py diff --git a/setup.py b/setup.py index b706e6f..9e1e775 100644 --- a/setup.py +++ b/setup.py @@ -2,15 +2,16 @@ from setuptools import setup, find_packages setup( name="galaxy.plugin.api", - version="0.69", + version="0.70", description="GOG Galaxy Integrations Python API", author='Galaxy team', author_email='galaxy@gog.com', packages=find_packages("src"), package_dir={'': 'src'}, + python_requires="~=3.13.0", # This package working with Python 3.13.x embedded in GOG Galaxy 2.0 install_requires=[ - "aiohttp>=3.5.4", - "certifi>=2019.3.9", + "aiohttp>=3.12.15", + "certifi>=2025.8.3", "psutil>=5.6.6; sys_platform == 'darwin'" ] ) diff --git a/src/.readthedocs.yml b/src/.readthedocs.yml index 051ee73..f489326 100644 --- a/src/.readthedocs.yml +++ b/src/.readthedocs.yml @@ -6,7 +6,7 @@ sphinx: formats: all python: - version: 3.7 + version: 3.13 install: - requirements: requirements.txt - requirements: docs/requirements.txt diff --git a/src/galaxy/api/errors.py b/src/galaxy/api/errors.py index fca141e..bf9335e 100644 --- a/src/galaxy/api/errors.py +++ b/src/galaxy/api/errors.py @@ -1,7 +1,7 @@ from galaxy.api.jsonrpc import ApplicationError, UnknownError -assert UnknownError +assert UnknownError is not None # UnknownError not used directly in errors.py, but we want to ensure it's defined class AuthenticationRequired(ApplicationError): def __init__(self, message="Authentication required", data=None): diff --git a/src/galaxy/api/importer.py b/src/galaxy/api/importer.py index f958f32..8f0591f 100644 --- a/src/galaxy/api/importer.py +++ b/src/galaxy/api/importer.py @@ -61,7 +61,7 @@ class Importer: context = await self._prepare_context(ids) self._task_manager.create_task( self._import_elements(ids, context), - "{} import".format(self._name), + f"{self._name} import", handle_exceptions=False ) except: @@ -76,7 +76,7 @@ class CollectionImporter(Importer): async def _import_element(self, id_, context_): try: - async for element in self._get(id_, context_): + async for element in await self._get(id_, context_): self._notification_success(id_, element) except ApplicationError as error: self._notification_failure(id_, error) diff --git a/src/galaxy/api/jsonrpc.py b/src/galaxy/api/jsonrpc.py index e4033b1..69c781f 100644 --- a/src/galaxy/api/jsonrpc.py +++ b/src/galaxy/api/jsonrpc.py @@ -297,7 +297,7 @@ class Connection(): @staticmethod def _parse_message(data): try: - jsonrpc_message = json.loads(data, encoding="utf-8") + jsonrpc_message = json.loads(data) if jsonrpc_message.get("jsonrpc") != "2.0": raise InvalidRequest() del jsonrpc_message["jsonrpc"] diff --git a/src/galaxy/api/plugin.py b/src/galaxy/api/plugin.py index 01f5268..4ae1676 100644 --- a/src/galaxy/api/plugin.py +++ b/src/galaxy/api/plugin.py @@ -299,7 +299,7 @@ class Plugin: return self._external_task_manager.create_task(coro, description) async def _pass_control(self): - while self._active: + while self._active and self._connection._active: try: self.tick() except Exception: diff --git a/src/galaxy/unittest/mock.py b/src/galaxy/unittest/mock.py index da2e033..8457bca 100644 --- a/src/galaxy/unittest/mock.py +++ b/src/galaxy/unittest/mock.py @@ -37,3 +37,21 @@ async def async_raise(error, loop_iterations_delay=0): if loop_iterations_delay > 0: await skip_loop(loop_iterations_delay) raise error + + +def delayed_return_value(return_value, loop_iterations_delay=0): + async def return_fn(*args, **kwargs): + for _ in range(loop_iterations_delay): + await asyncio.sleep(0) + return return_value + return return_fn + + +def delayed_return_value_iterable(return_value, loop_iterations_delay=0): + iterable = iter(return_value) + async def return_fn(*args, **kwargs): + for _ in range(loop_iterations_delay): + await asyncio.sleep(0.001) + last_value = next(iterable) + return last_value + return return_fn diff --git a/tests/conftest.py b/tests/conftest.py index cb0b87d..dc92707 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,6 @@ import logging from contextlib import ExitStack -from unittest.mock import MagicMock, patch +from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -12,12 +12,12 @@ from galaxy.unittest.mock import async_return_value @pytest.fixture() def reader(): stream = MagicMock(name="stream_reader") - stream.read = MagicMock() + stream.read = AsyncMock() yield stream @pytest.fixture() -async def writer(): +def writer(): stream = MagicMock(name="stream_writer") stream.drain.side_effect = lambda: async_return_value(None) yield stream @@ -34,7 +34,7 @@ def write(writer): @pytest.fixture() -async def plugin(reader, writer): +def plugin(reader, writer): """Return plugin instance with all feature methods mocked""" methods = ( "handshake_complete", @@ -73,13 +73,15 @@ async def plugin(reader, writer): "subscription_games_import_complete" ) + # Patch the class methods BEFORE creating the instance with ExitStack() as stack: for method in methods: stack.enter_context(patch.object(Plugin, method)) - - async with Plugin(Platform.Generic, "0.1", reader, writer, "token") as plugin: - plugin.shutdown.return_value = async_return_value(None) - yield plugin + + # Now create the plugin instance + plugin = Plugin(Platform.Generic, "0.1", reader, writer, "token") + plugin.shutdown.return_value = None + yield plugin @pytest.fixture(autouse=True) diff --git a/tests/test_achievements.py b/tests/test_achievements.py index d193354..d816047 100644 --- a/tests/test_achievements.py +++ b/tests/test_achievements.py @@ -5,7 +5,7 @@ from pytest import raises from galaxy.api.types import Achievement from galaxy.api.errors import BackendError -from galaxy.unittest.mock import async_return_value, skip_loop +from galaxy.unittest.mock import skip_loop from tests import create_message, get_messages @@ -22,7 +22,7 @@ def test_initialization_no_id_nor_name(): @pytest.mark.asyncio async def test_get_unlocked_achievements_success(plugin, read, write): - plugin.prepare_achievements_context.return_value = async_return_value(5) + plugin.prepare_achievements_context.return_value = 5 request = { "jsonrpc": "2.0", "id": "3", @@ -31,16 +31,17 @@ async def test_get_unlocked_achievements_success(plugin, read, write): "game_ids": ["14"] } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] - plugin.get_unlocked_achievements.return_value = async_return_value([ + read.side_effect = [create_message(request), b""] + plugin.get_unlocked_achievements.return_value = [ Achievement(achievement_id="lvl10", unlock_time=1548421241), Achievement(achievement_name="Got level 20", unlock_time=1548422395), Achievement(achievement_id="lvl30", achievement_name="Got level 30", unlock_time=1548495633) - ]) + ] await plugin.run() + await plugin.wait_closed() plugin.prepare_achievements_context.assert_called_with(["14"]) plugin.get_unlocked_achievements.assert_called_with("14", 5) - plugin.achievements_import_complete.asert_called_with() + plugin.achievements_import_complete.assert_called_with() assert get_messages(write) == [ { @@ -84,7 +85,7 @@ async def test_get_unlocked_achievements_success(plugin, read, write): (KeyError, 0, "Unknown error", "UnknownError") ]) async def test_get_unlocked_achievements_error(exception, code, message, internal_type, plugin, read, write): - plugin.prepare_achievements_context.return_value = async_return_value(None) + plugin.prepare_achievements_context.return_value = None request = { "jsonrpc": "2.0", "id": "3", @@ -94,11 +95,12 @@ async def test_get_unlocked_achievements_error(exception, code, message, interna } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_unlocked_achievements.side_effect = exception await plugin.run() + await plugin.wait_closed() plugin.get_unlocked_achievements.assert_called() - plugin.achievements_import_complete.asert_called_with() + plugin.achievements_import_complete.assert_called_with() assert get_messages(write) == [ { @@ -136,9 +138,10 @@ async def test_prepare_get_unlocked_achievements_context_error(plugin, read, wri "game_ids": ["14"] } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] await plugin.run() + await plugin.wait_closed() assert get_messages(write) == [ { @@ -155,8 +158,8 @@ async def test_prepare_get_unlocked_achievements_context_error(plugin, read, wri @pytest.mark.asyncio async def test_import_in_progress(plugin, read, write): - plugin.prepare_achievements_context.return_value = async_return_value(None) - plugin.get_unlocked_achievements.return_value = async_return_value([]) + plugin.prepare_achievements_context.return_value = None + plugin.get_unlocked_achievements.return_value = [] requests = [ { "jsonrpc": "2.0", @@ -176,12 +179,13 @@ async def test_import_in_progress(plugin, read, write): } ] read.side_effect = [ - async_return_value(create_message(requests[0])), - async_return_value(create_message(requests[1])), - async_return_value(b"", 10) + create_message(requests[0]), + create_message(requests[1]), + b"" ] await plugin.run() + await plugin.wait_closed() messages = get_messages(write) assert { diff --git a/tests/test_authenticate.py b/tests/test_authenticate.py index a878149..01d4abf 100644 --- a/tests/test_authenticate.py +++ b/tests/test_authenticate.py @@ -13,7 +13,7 @@ from galaxy.api.errors import ( Banned, AccessDenied, ) -from galaxy.unittest.mock import async_return_value, skip_loop +from galaxy.unittest.mock import skip_loop from tests import create_message, get_messages @@ -25,9 +25,10 @@ async def test_success(plugin, read, write): "id": "3", "method": "init_authentication" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] - plugin.authenticate.return_value = async_return_value(Authentication("132", "Zenek")) + read.side_effect = [create_message(request), b""] + plugin.authenticate.return_value = Authentication("132", "Zenek") await plugin.run() + await plugin.wait_closed() plugin.authenticate.assert_called_with() assert get_messages(write) == [ @@ -62,9 +63,10 @@ async def test_failure(plugin, read, write, error, code, message, internal_type) "method": "init_authentication" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.authenticate.side_effect = error() await plugin.run() + await plugin.wait_closed() plugin.authenticate.assert_called_with() assert get_messages(write) == [ @@ -92,9 +94,10 @@ async def test_stored_credentials(plugin, read, write): } } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] - plugin.authenticate.return_value = async_return_value(Authentication("132", "Zenek")) + read.side_effect = [create_message(request), b""] + plugin.authenticate.return_value = Authentication("132", "Zenek") await plugin.run() + await plugin.wait_closed() plugin.authenticate.assert_called_with(stored_credentials={"token": "ABC"}) write.assert_called() diff --git a/tests/test_chunk_messages.py b/tests/test_chunk_messages.py index 340c880..0521049 100644 --- a/tests/test_chunk_messages.py +++ b/tests/test_chunk_messages.py @@ -2,8 +2,6 @@ import json import pytest -from galaxy.unittest.mock import async_return_value - @pytest.mark.asyncio async def test_chunked_messages(plugin, read): @@ -16,8 +14,9 @@ async def test_chunked_messages(plugin, read): } message = json.dumps(request).encode() + b"\n" - read.side_effect = [async_return_value(message[:5]), async_return_value(message[5:]), async_return_value(b"")] + read.side_effect = [message[:5], message[5:], b""] await plugin.run() + await plugin.wait_closed() plugin.install_game.assert_called_with(game_id="3") @@ -41,8 +40,9 @@ async def test_joined_messages(plugin, read): ] data = b"".join([json.dumps(request).encode() + b"\n" for request in requests]) - read.side_effect = [async_return_value(data), async_return_value(b"")] + read.side_effect = [data, b""] await plugin.run() + await plugin.wait_closed() plugin.install_game.assert_called_with(game_id="3") plugin.launch_game.assert_called_with(game_id="3") @@ -58,6 +58,7 @@ async def test_not_finished(plugin, read): } message = json.dumps(request).encode() # no new line - read.side_effect = [async_return_value(message), async_return_value(b"")] + read.side_effect = [message, b""] await plugin.run() + await plugin.wait_closed() plugin.install_game.assert_not_called() diff --git a/tests/test_friends.py b/tests/test_friends.py index 07e9fd1..3b57d45 100644 --- a/tests/test_friends.py +++ b/tests/test_friends.py @@ -1,6 +1,6 @@ from galaxy.api.types import UserInfo from galaxy.api.errors import UnknownError -from galaxy.unittest.mock import async_return_value, skip_loop +from galaxy.unittest.mock import skip_loop import pytest @@ -15,14 +15,15 @@ async def test_get_friends_success(plugin, read, write): "method": "import_friends" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] - plugin.get_friends.return_value = async_return_value([ + read.side_effect = [create_message(request), b""] + plugin.get_friends.return_value = [ UserInfo("3", "Jan", "https://avatar.url/u3", None), UserInfo("5", "Ola", None, "https://profile.url/u5"), UserInfo("6", "Ola2", None), UserInfo("7", "Ola3"), - ]) + ] await plugin.run() + await plugin.wait_closed() plugin.get_friends.assert_called_with() assert get_messages(write) == [ @@ -49,9 +50,10 @@ async def test_get_friends_failure(plugin, read, write): "method": "import_friends" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_friends.side_effect = UnknownError() await plugin.run() + await plugin.wait_closed() plugin.get_friends.assert_called_with() assert get_messages(write) == [ @@ -73,6 +75,7 @@ async def test_add_friend(plugin, write): plugin.add_friend(friend) await skip_loop() + await plugin.wait_closed() assert get_messages(write) == [ { @@ -94,7 +97,7 @@ async def test_add_friend(plugin, write): async def test_remove_friend(plugin, write): plugin.remove_friend("5") await skip_loop() - + await plugin.wait_closed() assert get_messages(write) == [ { "jsonrpc": "2.0", @@ -112,7 +115,7 @@ async def test_update_friend_info(plugin, write): UserInfo("7", "Jakub", avatar_url="https://new-avatar.url/kuba2.jpg", profile_url="https://profile.url/kuba") ) await skip_loop() - + await plugin.wait_closed() assert get_messages(write) == [ { "jsonrpc": "2.0", diff --git a/tests/test_game_library_settings.py b/tests/test_game_library_settings.py index 400ab5a..68b3730 100644 --- a/tests/test_game_library_settings.py +++ b/tests/test_game_library_settings.py @@ -3,14 +3,13 @@ from unittest.mock import call import pytest from galaxy.api.types import GameLibrarySettings from galaxy.api.errors import BackendError -from galaxy.unittest.mock import async_return_value from tests import create_message, get_messages @pytest.mark.asyncio async def test_get_library_settings_success(plugin, read, write): - plugin.prepare_game_library_settings_context.return_value = async_return_value("abc") + plugin.prepare_game_library_settings_context.return_value = "abc" request = { "jsonrpc": "2.0", "id": "3", @@ -19,13 +18,14 @@ async def test_get_library_settings_success(plugin, read, write): "game_ids": ["3", "5", "7"] } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_game_library_settings.side_effect = [ - async_return_value(GameLibrarySettings("3", None, True)), - async_return_value(GameLibrarySettings("5", [], False)), - async_return_value(GameLibrarySettings("7", ["tag1", "tag2", "tag3"], None)), + GameLibrarySettings("3", None, True), + GameLibrarySettings("5", [], False), + GameLibrarySettings("7", ["tag1", "tag2", "tag3"], None), ] await plugin.run() + await plugin.wait_closed() plugin.get_game_library_settings.assert_has_calls([ call("3", "abc"), call("5", "abc"), @@ -84,7 +84,7 @@ async def test_get_library_settings_success(plugin, read, write): (KeyError, 0, "Unknown error", "UnknownError") ]) async def test_get_game_library_settings_error(exception, code, message, internal_type, plugin, read, write): - plugin.prepare_game_library_settings_context.return_value = async_return_value(None) + plugin.prepare_game_library_settings_context.return_value = None request = { "jsonrpc": "2.0", "id": "3", @@ -93,9 +93,10 @@ async def test_get_game_library_settings_error(exception, code, message, interna "game_ids": ["6"] } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_game_library_settings.side_effect = exception await plugin.run() + await plugin.wait_closed() plugin.get_game_library_settings.assert_called() plugin.game_library_settings_import_complete.assert_called_once_with() @@ -136,8 +137,9 @@ async def test_prepare_get_game_library_settings_context_error(plugin, read, wri "game_ids": ["6"] } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] await plugin.run() + await plugin.wait_closed() assert get_messages(write) == [ { @@ -154,7 +156,7 @@ async def test_prepare_get_game_library_settings_context_error(plugin, read, wri @pytest.mark.asyncio async def test_import_in_progress(plugin, read, write): - plugin.prepare_game_library_settings_context.return_value = async_return_value(None) + plugin.prepare_game_library_settings_context.return_value = None requests = [ { "jsonrpc": "2.0", @@ -174,12 +176,13 @@ async def test_import_in_progress(plugin, read, write): } ] read.side_effect = [ - async_return_value(create_message(requests[0])), - async_return_value(create_message(requests[1])), - async_return_value(b"", 10) + create_message(requests[0]), + create_message(requests[1]), + b"" ] await plugin.run() + await plugin.wait_closed() messages = get_messages(write) assert { diff --git a/tests/test_game_times.py b/tests/test_game_times.py index 81d798a..77469e4 100644 --- a/tests/test_game_times.py +++ b/tests/test_game_times.py @@ -3,14 +3,14 @@ from unittest.mock import call import pytest from galaxy.api.types import GameTime from galaxy.api.errors import BackendError -from galaxy.unittest.mock import async_return_value, skip_loop +from galaxy.unittest.mock import skip_loop from tests import create_message, get_messages @pytest.mark.asyncio async def test_get_game_time_success(plugin, read, write): - plugin.prepare_game_times_context.return_value = async_return_value("abc") + plugin.prepare_game_times_context.return_value = "abc" request = { "jsonrpc": "2.0", "id": "3", @@ -19,13 +19,14 @@ async def test_get_game_time_success(plugin, read, write): "game_ids": ["3", "5", "7"] } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_game_time.side_effect = [ - async_return_value(GameTime("3", 60, 1549550504)), - async_return_value(GameTime("5", 10, None)), - async_return_value(GameTime("7", None, 1549550502)), + GameTime("3", 60, 1549550504), + GameTime("5", 10, None), + GameTime("7", None, 1549550502), ] await plugin.run() + await plugin.wait_closed() plugin.get_game_time.assert_has_calls([ call("3", "abc"), call("5", "abc"), @@ -84,7 +85,7 @@ async def test_get_game_time_success(plugin, read, write): (KeyError, 0, "Unknown error", "UnknownError") ]) async def test_get_game_time_error(exception, code, message, internal_type, plugin, read, write): - plugin.prepare_game_times_context.return_value = async_return_value(None) + plugin.prepare_game_times_context.return_value = None request = { "jsonrpc": "2.0", "id": "3", @@ -93,9 +94,10 @@ async def test_get_game_time_error(exception, code, message, internal_type, plug "game_ids": ["6"] } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_game_time.side_effect = exception await plugin.run() + await plugin.wait_closed() plugin.get_game_time.assert_called() plugin.game_times_import_complete.assert_called_once_with() @@ -136,9 +138,9 @@ async def test_prepare_get_game_time_context_error(plugin, read, write): "game_ids": ["6"] } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] await plugin.run() - + await plugin.wait_closed() assert get_messages(write) == [ { "jsonrpc": "2.0", @@ -154,7 +156,7 @@ async def test_prepare_get_game_time_context_error(plugin, read, write): @pytest.mark.asyncio async def test_import_in_progress(plugin, read, write): - plugin.prepare_game_times_context.return_value = async_return_value(None) + plugin.prepare_game_times_context.return_value = None requests = [ { "jsonrpc": "2.0", @@ -174,13 +176,14 @@ async def test_import_in_progress(plugin, read, write): } ] read.side_effect = [ - async_return_value(create_message(requests[0])), - async_return_value(create_message(requests[1])), - async_return_value(b"", 10) + create_message(requests[0]), + create_message(requests[1]), + b"" ] await plugin.run() - + await plugin.wait_closed() + messages = get_messages(write) assert { "jsonrpc": "2.0", @@ -203,7 +206,7 @@ async def test_update_game(plugin, write): game_time = GameTime("3", 60, 1549550504) plugin.update_game_time(game_time) await skip_loop() - + await plugin.wait_closed() assert get_messages(write) == [ { "jsonrpc": "2.0", diff --git a/tests/test_install_game.py b/tests/test_install_game.py index fb739f0..c54c0c5 100644 --- a/tests/test_install_game.py +++ b/tests/test_install_game.py @@ -1,7 +1,5 @@ import pytest -from galaxy.unittest.mock import async_return_value - from tests import create_message @@ -15,6 +13,7 @@ async def test_success(plugin, read): } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"")] + read.side_effect = [create_message(request), b""] await plugin.run() + await plugin.wait_closed() plugin.install_game.assert_called_with(game_id="3") diff --git a/tests/test_internal.py b/tests/test_internal.py index b98b77a..7547723 100644 --- a/tests/test_internal.py +++ b/tests/test_internal.py @@ -2,7 +2,7 @@ import pytest from galaxy.api.plugin import Plugin from galaxy.api.consts import Platform -from galaxy.unittest.mock import async_return_value +from galaxy.unittest.mock import delayed_return_value_iterable from tests import create_message, get_messages @@ -20,8 +20,9 @@ async def test_get_capabilities(reader, writer, read, write): } token = "token" plugin = PluginImpl(Platform.Generic, "0.1", reader, writer, token) - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"")] + read.side_effect = [create_message(request), b""] await plugin.run() + await plugin.wait_closed() assert get_messages(write) == [ { "jsonrpc": "2.0", @@ -44,7 +45,7 @@ async def test_shutdown(plugin, read, write): "id": "5", "method": "shutdown" } - read.side_effect = [async_return_value(create_message(request))] + read.side_effect = [create_message(request)] await plugin.run() await plugin.wait_closed() plugin.shutdown.assert_called_with() @@ -64,8 +65,9 @@ async def test_ping(plugin, read, write): "id": "7", "method": "ping" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"")] + read.side_effect = [create_message(request), b""] await plugin.run() + await plugin.wait_closed() assert get_messages(write) == [ { "jsonrpc": "2.0", @@ -77,8 +79,9 @@ async def test_ping(plugin, read, write): @pytest.mark.asyncio async def test_tick_before_handshake(plugin, read): - read.side_effect = [async_return_value(b"")] + read.side_effect = [b""] await plugin.run() + await plugin.wait_closed() plugin.tick.assert_not_called() @@ -90,6 +93,7 @@ async def test_tick_after_handshake(plugin, read): "method": "initialize_cache", "params": {"data": {}} } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"")] + read.side_effect = delayed_return_value_iterable([create_message(request), b""], 1) await plugin.run() + await plugin.wait_closed() plugin.tick.assert_called_with() diff --git a/tests/test_launch_game.py b/tests/test_launch_game.py index 4ab22c6..1539b0b 100644 --- a/tests/test_launch_game.py +++ b/tests/test_launch_game.py @@ -1,7 +1,5 @@ import pytest -from galaxy.unittest.mock import async_return_value - from tests import create_message @@ -15,6 +13,7 @@ async def test_success(plugin, read): } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"")] + read.side_effect = [create_message(request), b""] await plugin.run() + await plugin.wait_closed() plugin.launch_game.assert_called_with(game_id="3") diff --git a/tests/test_launch_platform_client.py b/tests/test_launch_platform_client.py index 3536047..263c5ca 100644 --- a/tests/test_launch_platform_client.py +++ b/tests/test_launch_platform_client.py @@ -1,7 +1,5 @@ import pytest -from galaxy.unittest.mock import async_return_value - from tests import create_message @pytest.mark.asyncio @@ -11,7 +9,8 @@ async def test_success(plugin, read): "method": "launch_platform_client" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"")] - plugin.launch_platform_client.return_value = async_return_value(None) + read.side_effect = [create_message(request), b""] + plugin.launch_platform_client.return_value = None await plugin.run() + await plugin.wait_closed() plugin.launch_platform_client.assert_called_with() diff --git a/tests/test_local_games.py b/tests/test_local_games.py index c90cd85..1486a39 100644 --- a/tests/test_local_games.py +++ b/tests/test_local_games.py @@ -3,7 +3,7 @@ import pytest from galaxy.api.types import LocalGame from galaxy.api.consts import LocalGameState from galaxy.api.errors import UnknownError, FailedParsingManifest -from galaxy.unittest.mock import async_return_value, skip_loop +from galaxy.unittest.mock import skip_loop from tests import create_message, get_messages @@ -15,14 +15,15 @@ async def test_success(plugin, read, write): "id": "3", "method": "import_local_games" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] - plugin.get_local_games.return_value = async_return_value([ + plugin.get_local_games.return_value = [ LocalGame("1", LocalGameState.Running), LocalGame("2", LocalGameState.Installed), LocalGame("3", LocalGameState.Installed | LocalGameState.Running) - ]) + ] await plugin.run() + await plugin.wait_closed() plugin.get_local_games.assert_called_with() assert get_messages(write) == [ @@ -63,9 +64,10 @@ async def test_failure(plugin, read, write, error, code, message, internal_type) "id": "3", "method": "import_local_games" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_local_games.side_effect = error() await plugin.run() + await plugin.wait_closed() plugin.get_local_games.assert_called_with() assert get_messages(write) == [ diff --git a/tests/test_local_size.py b/tests/test_local_size.py index 3929d24..cbffbf0 100644 --- a/tests/test_local_size.py +++ b/tests/test_local_size.py @@ -1,29 +1,30 @@ from unittest.mock import call - import pytest from galaxy.api.errors import FailedParsingManifest -from galaxy.unittest.mock import async_return_value +from galaxy.unittest.mock import delayed_return_value from tests import create_message, get_messages + @pytest.mark.asyncio async def test_get_local_size_success(plugin, read, write): context = {'abc': 'def'} - plugin.prepare_local_size_context.return_value = async_return_value(context) + plugin.prepare_local_size_context.return_value = context request = { "jsonrpc": "2.0", "id": "11", "method": "start_local_size_import", "params": {"game_ids": ["777", "13", "42"]} } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_local_size.side_effect = [ - async_return_value(100000000000, 1), - async_return_value(None), - async_return_value(3333333) + 100000000000, + None, + 3333333 ] await plugin.run() + await plugin.wait_closed() plugin.get_local_size.assert_has_calls([ call("777", context), call("13", context), @@ -31,12 +32,17 @@ async def test_get_local_size_success(plugin, read, write): ]) plugin.local_size_import_complete.assert_called_once_with() - assert get_messages(write) == [ - { - "jsonrpc": "2.0", - "id": "11", - "result": None - }, + messages = get_messages(write) + prepare_local_size_context_response = { + "jsonrpc": "2.0", + "id": "11", + "result": None + } + # response for prepare_local_size_context may be returned before or after + # notifications about import success + assert prepare_local_size_context_response in messages + messages.remove(prepare_local_size_context_response) + assert messages == [ { "jsonrpc": "2.0", "method": "local_size_import_success", @@ -76,16 +82,17 @@ async def test_get_local_size_success(plugin, read, write): async def test_get_local_size_error(exception, code, message, internal_type, plugin, read, write): game_id = "6" request_id = "55" - plugin.prepare_local_size_context.return_value = async_return_value(None) + plugin.prepare_local_size_context.return_value = None request = { "jsonrpc": "2.0", "id": request_id, "method": "start_local_size_import", "params": {"game_ids": [game_id]} } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_local_size.side_effect = exception await plugin.run() + await plugin.wait_closed() plugin.get_local_size.assert_called() plugin.local_size_import_complete.assert_called_once_with() @@ -132,8 +139,9 @@ async def test_prepare_get_local_size_context_error(plugin, read, write): "method": "start_local_size_import", "params": {"game_ids": ["6"]} } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] await plugin.run() + await plugin.wait_closed() assert get_messages(write) == [ { "jsonrpc": "2.0", @@ -152,8 +160,10 @@ async def test_prepare_get_local_size_context_error(plugin, read, write): @pytest.mark.asyncio async def test_import_already_in_progress_error(plugin, read, write): - plugin.prepare_local_size_context.return_value = async_return_value(None) - plugin.get_local_size.return_value = async_return_value(100, 5) + plugin.prepare_local_size_context.return_value = None + print("******", plugin.get_local_size) + + plugin.get_local_size.side_effect = delayed_return_value(100, 5) requests = [ { "jsonrpc": "2.0", @@ -173,12 +183,13 @@ async def test_import_already_in_progress_error(plugin, read, write): } ] read.side_effect = [ - async_return_value(create_message(requests[0])), - async_return_value(create_message(requests[1])), - async_return_value(b"", 10) + create_message(requests[0]), + create_message(requests[1]), + b"" ] await plugin.run() + await plugin.wait_closed() responses = get_messages(write) assert { diff --git a/tests/test_os_compatibility.py b/tests/test_os_compatibility.py index e871920..a8e0ab5 100644 --- a/tests/test_os_compatibility.py +++ b/tests/test_os_compatibility.py @@ -3,7 +3,6 @@ from unittest.mock import call import pytest from galaxy.api.consts import OSCompatibility from galaxy.api.errors import BackendError -from galaxy.unittest.mock import async_return_value from tests import create_message, get_messages @@ -11,20 +10,21 @@ from tests import create_message, get_messages @pytest.mark.asyncio async def test_get_os_compatibility_success(plugin, read, write): context = "abc" - plugin.prepare_os_compatibility_context.return_value = async_return_value(context) + plugin.prepare_os_compatibility_context.return_value = context request = { "jsonrpc": "2.0", "id": "11", "method": "start_os_compatibility_import", "params": {"game_ids": ["666", "13", "42"]} } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_os_compatibility.side_effect = [ - async_return_value(OSCompatibility.Linux), - async_return_value(None), - async_return_value(OSCompatibility.Windows | OSCompatibility.MacOS), + OSCompatibility.Linux, + None, + OSCompatibility.Windows | OSCompatibility.MacOS, ] await plugin.run() + await plugin.wait_closed() plugin.get_os_compatibility.assert_has_calls([ call("666", context), call("13", context), @@ -78,16 +78,17 @@ async def test_get_os_compatibility_success(plugin, read, write): async def test_get_os_compatibility_error(exception, code, message, internal_type, plugin, read, write): game_id = "6" request_id = "55" - plugin.prepare_os_compatibility_context.return_value = async_return_value(None) + plugin.prepare_os_compatibility_context.return_value = None request = { "jsonrpc": "2.0", "id": request_id, "method": "start_os_compatibility_import", "params": {"game_ids": [game_id]} } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_os_compatibility.side_effect = exception await plugin.run() + await plugin.wait_closed() plugin.get_os_compatibility.assert_called() plugin.os_compatibility_import_complete.assert_called_once_with() @@ -127,8 +128,9 @@ async def test_prepare_get_os_compatibility_context_error(plugin, read, write): "method": "start_os_compatibility_import", "params": {"game_ids": ["6"]} } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] await plugin.run() + await plugin.wait_closed() assert get_messages(write) == [ { @@ -145,7 +147,7 @@ async def test_prepare_get_os_compatibility_context_error(plugin, read, write): @pytest.mark.asyncio async def test_import_already_in_progress_error(plugin, read, write): - plugin.prepare_os_compatibility_context.return_value = async_return_value(None) + plugin.prepare_os_compatibility_context.return_value = None requests = [ { "jsonrpc": "2.0", @@ -165,12 +167,13 @@ async def test_import_already_in_progress_error(plugin, read, write): } ] read.side_effect = [ - async_return_value(create_message(requests[0])), - async_return_value(create_message(requests[1])), - async_return_value(b"", 10) + create_message(requests[0]), + create_message(requests[1]), + b"" ] await plugin.run() + await plugin.wait_closed() responses = get_messages(write) assert { diff --git a/tests/test_owned_games.py b/tests/test_owned_games.py index 49c099d..aeddc6d 100644 --- a/tests/test_owned_games.py +++ b/tests/test_owned_games.py @@ -3,7 +3,7 @@ import pytest from galaxy.api.types import Game, Dlc, LicenseInfo from galaxy.api.consts import LicenseType from galaxy.api.errors import UnknownError -from galaxy.unittest.mock import async_return_value, skip_loop +from galaxy.unittest.mock import skip_loop from tests import create_message, get_messages @@ -15,9 +15,9 @@ async def test_success(plugin, read, write): "id": "3", "method": "import_owned_games" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] - plugin.get_owned_games.return_value = async_return_value([ + plugin.get_owned_games.return_value = [ Game("3", "Doom", None, LicenseInfo(LicenseType.SinglePurchase, None)), Game( "5", @@ -27,8 +27,9 @@ async def test_success(plugin, read, write): Dlc("8", "Temerian Armor Set", LicenseInfo(LicenseType.FreeToPlay, None)), ], LicenseInfo(LicenseType.SinglePurchase, None)) - ]) + ] await plugin.run() + await plugin.wait_closed() plugin.get_owned_games.assert_called_with() assert get_messages(write) == [ { @@ -80,9 +81,10 @@ async def test_failure(plugin, read, write): "method": "import_owned_games" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_owned_games.side_effect = UnknownError() await plugin.run() + await plugin.wait_closed() plugin.get_owned_games.assert_called_with() assert get_messages(write) == [ { diff --git a/tests/test_persistent_cache.py b/tests/test_persistent_cache.py index 8e9834f..f0efee3 100644 --- a/tests/test_persistent_cache.py +++ b/tests/test_persistent_cache.py @@ -1,6 +1,6 @@ import pytest -from galaxy.unittest.mock import async_return_value, skip_loop +from galaxy.unittest.mock import skip_loop from tests import create_message, get_messages @@ -42,10 +42,11 @@ async def test_initialize_cache(plugin, read, write, cache_data): "method": "initialize_cache", "params": {"data": cache_data} } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"")] + read.side_effect = [create_message(request), b""] assert {} == plugin.persistent_cache await plugin.run() + await plugin.wait_closed() plugin.handshake_complete.assert_called_once_with() assert cache_data == plugin.persistent_cache assert_rpc_response(write, response_id=request_id) diff --git a/tests/test_refresh_credentials.py b/tests/test_refresh_credentials.py index ae454ea..b3fd27f 100644 --- a/tests/test_refresh_credentials.py +++ b/tests/test_refresh_credentials.py @@ -1,7 +1,6 @@ import pytest import asyncio -from galaxy.unittest.mock import async_return_value from tests import create_message, get_messages from galaxy.api.errors import ( BackendNotAvailable, BackendTimeout, BackendError, InvalidCredentials, NetworkError, AccessDenied, UnknownError @@ -24,7 +23,7 @@ async def test_refresh_credentials_success(plugin, read, write): "result": refreshed_credentials } # 2 loop iterations delay is to force sending response after request has been sent - read.side_effect = [async_return_value(create_message(response), loop_iterations_delay=2)] + read.side_effect = [create_message(response), b""] result = await plugin.refresh_credentials({}, False) assert get_messages(write) == [ @@ -55,7 +54,7 @@ async def test_refresh_credentials_failure(exception, plugin, read, write): } # 2 loop iterations delay is to force sending response after request has been sent - read.side_effect = [async_return_value(create_message(response), loop_iterations_delay=2)] + read.side_effect = [create_message(response), b""] with pytest.raises(JsonRpcError) as e: await plugin.refresh_credentials({}, False) diff --git a/tests/test_shutdown_platform_client.py b/tests/test_shutdown_platform_client.py index c2dc3f1..0680d5b 100644 --- a/tests/test_shutdown_platform_client.py +++ b/tests/test_shutdown_platform_client.py @@ -1,6 +1,5 @@ import pytest -from galaxy.unittest.mock import async_return_value from tests import create_message @@ -11,7 +10,8 @@ async def test_success(plugin, read): "method": "shutdown_platform_client" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"")] - plugin.shutdown_platform_client.return_value = async_return_value(None) + read.side_effect = [create_message(request), b""] + plugin.shutdown_platform_client.return_value = None await plugin.run() + await plugin.wait_closed() plugin.shutdown_platform_client.assert_called_with() diff --git a/tests/test_stream_line_reader.py b/tests/test_stream_line_reader.py index 64226f5..b3dbe5b 100644 --- a/tests/test_stream_line_reader.py +++ b/tests/test_stream_line_reader.py @@ -1,7 +1,6 @@ import pytest from galaxy.reader import StreamLineReader -from galaxy.unittest.mock import async_return_value @pytest.fixture() @@ -11,14 +10,14 @@ def stream_line_reader(reader): @pytest.mark.asyncio async def test_message(stream_line_reader, read): - read.return_value = async_return_value(b"a\n") + read.return_value = b"a\n" assert await stream_line_reader.readline() == b"a" read.assert_called_once() @pytest.mark.asyncio async def test_separate_messages(stream_line_reader, read): - read.side_effect = [async_return_value(b"a\n"), async_return_value(b"b\n")] + read.side_effect = [b"a\n", b"b\n"] assert await stream_line_reader.readline() == b"a" assert await stream_line_reader.readline() == b"b" assert read.call_count == 2 @@ -26,7 +25,7 @@ async def test_separate_messages(stream_line_reader, read): @pytest.mark.asyncio async def test_connected_messages(stream_line_reader, read): - read.return_value = async_return_value(b"a\nb\n") + read.return_value = b"a\nb\n" assert await stream_line_reader.readline() == b"a" assert await stream_line_reader.readline() == b"b" read.assert_called_once() @@ -34,13 +33,13 @@ async def test_connected_messages(stream_line_reader, read): @pytest.mark.asyncio async def test_cut_message(stream_line_reader, read): - read.side_effect = [async_return_value(b"a"), async_return_value(b"b\n")] + read.side_effect = [b"a", b"b\n"] assert await stream_line_reader.readline() == b"ab" assert read.call_count == 2 @pytest.mark.asyncio async def test_half_message(stream_line_reader, read): - read.side_effect = [async_return_value(b"a"), async_return_value(b"")] + read.side_effect = [b"a", b""] assert await stream_line_reader.readline() == b"" assert read.call_count == 2 diff --git a/tests/test_subscriptions.py b/tests/test_subscriptions.py index 91439f8..499e539 100644 --- a/tests/test_subscriptions.py +++ b/tests/test_subscriptions.py @@ -3,7 +3,6 @@ import pytest from galaxy.api.types import Subscription, SubscriptionGame from galaxy.api.consts import SubscriptionDiscovery from galaxy.api.errors import FailedParsingManifest, BackendError, UnknownError -from galaxy.unittest.mock import async_return_value from tests import create_message, get_messages @@ -14,14 +13,15 @@ async def test_get_subscriptions_success(plugin, read, write): "id": "3", "method": "import_subscriptions" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] - plugin.get_subscriptions.return_value = async_return_value([ + plugin.get_subscriptions.return_value = [ Subscription("1"), Subscription("2", False, subscription_discovery=SubscriptionDiscovery.AUTOMATIC), Subscription("3", True, 1580899100, SubscriptionDiscovery.USER_ENABLED) - ]) + ] await plugin.run() + await plugin.wait_closed() plugin.get_subscriptions.assert_called_with() assert get_messages(write) == [ @@ -65,9 +65,10 @@ async def test_get_subscriptions_failure_generic(plugin, read, write, error, cod "id": "3", "method": "import_subscriptions" } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_subscriptions.side_effect = error() await plugin.run() + await plugin.wait_closed() plugin.get_subscriptions.assert_called_with() assert get_messages(write) == [ @@ -85,7 +86,7 @@ async def test_get_subscriptions_failure_generic(plugin, read, write, error, cod @pytest.mark.asyncio async def test_get_subscription_games_success(plugin, read, write): - plugin.prepare_subscription_games_context.return_value = async_return_value(5) + plugin.prepare_subscription_games_context.return_value = 5 request = { "jsonrpc": "2.0", "id": "3", @@ -94,22 +95,28 @@ async def test_get_subscription_games_success(plugin, read, write): "subscription_names": ["sub_a"] } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] - async def sub_games(): + # Create an async generator that yields the games + async def mock_subscription_games_generator(subscription_name, context): games = [ - SubscriptionGame(game_title="game A", game_id="game_A"), - SubscriptionGame(game_title="game B", game_id="game_B", start_time=1548495632), - SubscriptionGame(game_title="game C", game_id="game_C", end_time=1548495633), - SubscriptionGame(game_title="game D", game_id="game_D", start_time=1548495632, end_time=1548495633), - ] - yield [game for game in games] + # first chunk of the games + [SubscriptionGame(game_title="game A", game_id="game_A"), + SubscriptionGame(game_title="game B", game_id="game_B", start_time=1548495632), + SubscriptionGame(game_title="game C", game_id="game_C", end_time=1548495633)], + # second chunk of the games + [SubscriptionGame(game_title="game D", game_id="game_D", start_time=1548495632, end_time=1548495633)], + ] + for game in games: + yield game + + plugin.get_subscription_games.side_effect = mock_subscription_games_generator - plugin.get_subscription_games.return_value = sub_games() await plugin.run() + await plugin.wait_closed() plugin.prepare_subscription_games_context.assert_called_with(["sub_a"]) plugin.get_subscription_games.assert_called_with("sub_a", 5) - plugin.subscription_games_import_complete.asert_called_with() + plugin.subscription_games_import_complete.assert_called_with() assert get_messages(write) == [ { @@ -137,6 +144,15 @@ async def test_get_subscription_games_success(plugin, read, write): "game_id": "game_C", "end_time": 1548495633 }, + ] + } + }, + { + "jsonrpc": "2.0", + "method": "subscription_games_import_success", + "params": { + "subscription_name": "sub_a", + "subscription_games": [ { "game_title": "game D", "game_id": "game_D", @@ -163,7 +179,7 @@ async def test_get_subscription_games_success(plugin, read, write): @pytest.mark.asyncio async def test_get_subscription_games_success_empty(plugin, read, write): - plugin.prepare_subscription_games_context.return_value = async_return_value(5) + plugin.prepare_subscription_games_context.return_value = 5 request = { "jsonrpc": "2.0", "id": "3", @@ -172,16 +188,17 @@ async def test_get_subscription_games_success_empty(plugin, read, write): "subscription_names": ["sub_a"] } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] async def sub_games(): yield None plugin.get_subscription_games.return_value = sub_games() await plugin.run() + await plugin.wait_closed() plugin.prepare_subscription_games_context.assert_called_with(["sub_a"]) plugin.get_subscription_games.assert_called_with("sub_a", 5) - plugin.subscription_games_import_complete.asert_called_with() + plugin.subscription_games_import_complete.assert_called_with() assert get_messages(write) == [ { @@ -218,7 +235,7 @@ async def test_get_subscription_games_success_empty(plugin, read, write): (KeyError, 0, "Unknown error", "UnknownError") ]) async def test_get_subscription_games_error(exception, code, message, internal_type, plugin, read, write): - plugin.prepare_subscription_games_context.return_value = async_return_value(None) + plugin.prepare_subscription_games_context.return_value = None request = { "jsonrpc": "2.0", "id": "3", @@ -228,11 +245,12 @@ async def test_get_subscription_games_error(exception, code, message, internal_t } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_subscription_games.side_effect = exception await plugin.run() + await plugin.wait_closed() plugin.get_subscription_games.assert_called() - plugin.subscription_games_import_complete.asert_called_with() + plugin.subscription_games_import_complete.assert_called_with() assert get_messages(write) == [ { @@ -280,8 +298,9 @@ async def test_prepare_get_subscription_games_context_error(plugin, read, write) "method": "start_subscription_games_import", "params": {"subscription_names": ["sub_a", "sub_b"]} } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] await plugin.run() + await plugin.wait_closed() assert get_messages(write) == [ { "jsonrpc": "2.0", @@ -300,7 +319,7 @@ async def test_prepare_get_subscription_games_context_error(plugin, read, write) @pytest.mark.asyncio async def test_import_already_in_progress_error(plugin, read, write): - plugin.prepare_subscription_games_context.return_value = async_return_value(None) + plugin.prepare_subscription_games_context.return_value = None requests = [ { "jsonrpc": "2.0", @@ -320,13 +339,13 @@ async def test_import_already_in_progress_error(plugin, read, write): } ] read.side_effect = [ - async_return_value(create_message(requests[0])), - async_return_value(create_message(requests[1])), - async_return_value(b"", 10) + create_message(requests[0]), + create_message(requests[1]), + b"" ] await plugin.run() - + await plugin.wait_closed() responses = get_messages(write) assert { "jsonrpc": "2.0", diff --git a/tests/test_uninstall_game.py b/tests/test_uninstall_game.py index 1ec79a7..a93af24 100644 --- a/tests/test_uninstall_game.py +++ b/tests/test_uninstall_game.py @@ -1,7 +1,5 @@ import pytest -from galaxy.unittest.mock import async_return_value - from tests import create_message @pytest.mark.asyncio @@ -13,7 +11,8 @@ async def test_success(plugin, read): "game_id": "3" } } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"")] + read.side_effect = [create_message(request), b""] plugin.get_owned_games.return_value = None await plugin.run() + await plugin.wait_closed() plugin.uninstall_game.assert_called_with(game_id="3") diff --git a/tests/test_user_presence.py b/tests/test_user_presence.py index efa32ed..06c9bdd 100644 --- a/tests/test_user_presence.py +++ b/tests/test_user_presence.py @@ -5,7 +5,7 @@ import pytest from galaxy.api.consts import PresenceState from galaxy.api.errors import BackendError from galaxy.api.types import UserPresence -from galaxy.unittest.mock import async_return_value, skip_loop +from galaxy.unittest.mock import skip_loop from tests import create_message, get_messages @@ -13,52 +13,53 @@ from tests import create_message, get_messages async def test_get_user_presence_success(plugin, read, write): context = "abc" user_id_list = ["666", "13", "42", "69", "22"] - plugin.prepare_user_presence_context.return_value = async_return_value(context) + plugin.prepare_user_presence_context.return_value = context request = { "jsonrpc": "2.0", "id": "11", "method": "start_user_presence_import", "params": {"user_id_list": user_id_list} } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_user_presence.side_effect = [ - async_return_value(UserPresence( + UserPresence( PresenceState.Unknown, "game-id1", None, "unknown state", None - )), - async_return_value(UserPresence( + ), + UserPresence( PresenceState.Offline, None, None, "Going to grandma's house", None - )), - async_return_value(UserPresence( + ), + UserPresence( PresenceState.Online, "game-id3", "game-title3", "Pew pew", None - )), - async_return_value(UserPresence( + ), + UserPresence( PresenceState.Away, None, "game-title4", "AFKKTHXBY", None - )), - async_return_value(UserPresence( + ), + UserPresence( PresenceState.Away, None, "game-title5", None, "Playing game-title5: In Menu" - )), + ), ] await plugin.run() + await plugin.wait_closed() plugin.get_user_presence.assert_has_calls([ call(user_id, context) for user_id in user_id_list ]) @@ -146,16 +147,17 @@ async def test_get_user_presence_success(plugin, read, write): async def test_get_user_presence_error(exception, code, message, internal_type, plugin, read, write): user_id = "69" request_id = "55" - plugin.prepare_user_presence_context.return_value = async_return_value(None) + plugin.prepare_user_presence_context.return_value = None request = { "jsonrpc": "2.0", "id": request_id, "method": "start_user_presence_import", "params": {"user_id_list": [user_id]} } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] plugin.get_user_presence.side_effect = exception await plugin.run() + await plugin.wait_closed() plugin.get_user_presence.assert_called() plugin.user_presence_import_complete.assert_called_once_with() @@ -197,9 +199,9 @@ async def test_prepare_get_user_presence_context_error(plugin, read, write): "method": "start_user_presence_import", "params": {"user_id_list": ["6"]} } - read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] + read.side_effect = [create_message(request), b""] await plugin.run() - + await plugin.wait_closed() assert get_messages(write) == [ { "jsonrpc": "2.0", @@ -217,7 +219,7 @@ async def test_prepare_get_user_presence_context_error(plugin, read, write): @pytest.mark.asyncio async def test_import_already_in_progress_error(plugin, read, write): - plugin.prepare_user_presence_context.return_value = async_return_value(None) + plugin.prepare_user_presence_context.return_value = None requests = [ { "jsonrpc": "2.0", @@ -237,13 +239,13 @@ async def test_import_already_in_progress_error(plugin, read, write): } ] read.side_effect = [ - async_return_value(create_message(requests[0])), - async_return_value(create_message(requests[1])), - async_return_value(b"", 10) + create_message(requests[0]), + create_message(requests[1]), + b"" ] await plugin.run() - + await plugin.wait_closed() responses = get_messages(write) assert { "jsonrpc": "2.0",