mirror of
https://github.com/gogcom/galaxy-integrations-python-api.git
synced 2025-12-24 07:28:14 -05:00
GPI-1109 Implement get_game_size
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,3 +8,4 @@ Pipfile
|
||||
.idea
|
||||
docs/source/_build
|
||||
.mypy_cache
|
||||
.pytest_cache
|
||||
|
||||
@@ -114,6 +114,7 @@ class Feature(Enum):
|
||||
ImportGameLibrarySettings = "ImportGameLibrarySettings"
|
||||
ImportOSCompatibility = "ImportOSCompatibility"
|
||||
ImportUserPresence = "ImportUserPresence"
|
||||
ImportLocalSize = "ImportLocalSize"
|
||||
|
||||
|
||||
class LicenseType(Enum):
|
||||
|
||||
@@ -166,6 +166,16 @@ class Plugin:
|
||||
self._user_presence_import_finished,
|
||||
self.user_presence_import_complete
|
||||
)
|
||||
self._local_size_importer = Importer(
|
||||
self._external_task_manager,
|
||||
"local size",
|
||||
self.get_local_size,
|
||||
self.prepare_local_size_context,
|
||||
self._local_size_import_success,
|
||||
self._local_size_import_failure,
|
||||
self._local_size_import_finished,
|
||||
self.local_size_import_complete
|
||||
)
|
||||
|
||||
# internal
|
||||
self._register_method("shutdown", self._shutdown, internal=True)
|
||||
@@ -233,6 +243,9 @@ class Plugin:
|
||||
self._register_method("start_user_presence_import", self._start_user_presence_import)
|
||||
self._detect_feature(Feature.ImportUserPresence, ["get_user_presence"])
|
||||
|
||||
self._register_method("start_local_size_import", self._start_local_size_import)
|
||||
self._detect_feature(Feature.ImportLocalSize, ["get_local_size"])
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
@@ -613,6 +626,27 @@ class Plugin:
|
||||
def _user_presence_import_finished(self) -> None:
|
||||
self._connection.send_notification("user_presence_import_finished", None)
|
||||
|
||||
def _local_size_import_success(self, game_id: str, size: Optional[int]) -> None:
|
||||
self._connection.send_notification(
|
||||
"local_size_import_success",
|
||||
{
|
||||
"game_id": game_id,
|
||||
"local_size": size
|
||||
}
|
||||
)
|
||||
|
||||
def _local_size_import_failure(self, game_id: str, error: ApplicationError) -> None:
|
||||
self._connection.send_notification(
|
||||
"local_size_import_failure",
|
||||
{
|
||||
"game_id": game_id,
|
||||
"error": error.json()
|
||||
}
|
||||
)
|
||||
|
||||
def _local_size_import_finished(self) -> None:
|
||||
self._connection.send_notification("local_size_import_finished", None)
|
||||
|
||||
def lost_authentication(self) -> None:
|
||||
"""Notify the client that integration has lost authentication for the
|
||||
current user and is unable to perform actions which would require it.
|
||||
@@ -966,7 +1000,7 @@ class Plugin:
|
||||
await self._user_presence_importer.start(user_id_list)
|
||||
|
||||
async def prepare_user_presence_context(self, user_id_list: List[str]) -> Any:
|
||||
"""Override this method to prepare context for get_user_presence.
|
||||
"""Override this method to prepare context for :meth:`get_user_presence`.
|
||||
This allows for optimizations like batch requests to platform API.
|
||||
Default implementation returns None.
|
||||
|
||||
@@ -988,6 +1022,32 @@ class Plugin:
|
||||
def user_presence_import_complete(self) -> None:
|
||||
"""Override this method to handle operations after presence import is finished (like updating cache)."""
|
||||
|
||||
async def _start_local_size_import(self, game_ids: List[str]) -> None:
|
||||
await self._local_size_importer.start(game_ids)
|
||||
|
||||
async def prepare_local_size_context(self, game_ids: List[str]) -> Any:
|
||||
"""Override this method to prepare context for :meth:`get_local_size`
|
||||
Default implementation returns None.
|
||||
|
||||
:param game_ids: the ids of the games for which information about size is imported
|
||||
:return: context
|
||||
"""
|
||||
return None
|
||||
|
||||
async def get_local_size(self, game_id: str, context: Any) -> int:
|
||||
"""Override this method to return installed game size in bytes.
|
||||
|
||||
.. note::
|
||||
It is preferable to use more efficient way of game size retrieval than iterating over all local files.
|
||||
|
||||
:param context: the value returned from :meth:`prepare_local_size_context`
|
||||
:return: game size in bytes
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def local_size_import_complete(self) -> None:
|
||||
"""Override this method to handle operations after local game size import is finished (like updating cache)."""
|
||||
|
||||
|
||||
def create_and_run_plugin(plugin_class, argv):
|
||||
"""Call this method as an entry point for the implemented integration.
|
||||
|
||||
@@ -64,6 +64,9 @@ async def plugin(reader, writer):
|
||||
"get_user_presence",
|
||||
"prepare_user_presence_context",
|
||||
"user_presence_import_complete",
|
||||
"get_local_size",
|
||||
"prepare_local_size_context",
|
||||
"local_size_import_complete",
|
||||
)
|
||||
|
||||
with ExitStack() as stack:
|
||||
|
||||
@@ -17,7 +17,8 @@ def test_base_class():
|
||||
Feature.LaunchPlatformClient,
|
||||
Feature.ImportGameLibrarySettings,
|
||||
Feature.ImportOSCompatibility,
|
||||
Feature.ImportUserPresence
|
||||
Feature.ImportUserPresence,
|
||||
Feature.ImportLocalSize
|
||||
}
|
||||
|
||||
|
||||
|
||||
188
tests/test_local_size.py
Normal file
188
tests/test_local_size.py
Normal file
@@ -0,0 +1,188 @@
|
||||
from unittest.mock import call
|
||||
|
||||
import pytest
|
||||
from galaxy.api.errors import FailedParsingManifest
|
||||
from galaxy.unittest.mock import async_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)
|
||||
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)]
|
||||
plugin.get_local_size.side_effect = [
|
||||
async_return_value(100000000000),
|
||||
async_return_value(None),
|
||||
async_return_value(3333333)
|
||||
]
|
||||
await plugin.run()
|
||||
plugin.get_local_size.assert_has_calls([
|
||||
call("777", context),
|
||||
call("13", context),
|
||||
call("42", context)
|
||||
])
|
||||
plugin.local_size_import_complete.assert_called_once_with()
|
||||
|
||||
assert get_messages(write) == [
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "11",
|
||||
"result": None
|
||||
},
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "local_size_import_success",
|
||||
"params": {
|
||||
"game_id": "777",
|
||||
"local_size": 100000000000
|
||||
}
|
||||
},
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "local_size_import_success",
|
||||
"params": {
|
||||
"game_id": "13",
|
||||
"local_size": None
|
||||
}
|
||||
},
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "local_size_import_success",
|
||||
"params": {
|
||||
"game_id": "42",
|
||||
"local_size": 3333333
|
||||
}
|
||||
},
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "local_size_import_finished",
|
||||
"params": None
|
||||
}
|
||||
]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("exception,code,message", [
|
||||
(FailedParsingManifest, 200, "Failed parsing manifest"),
|
||||
(KeyError, 0, "Unknown error")
|
||||
])
|
||||
async def test_get_local_size_error(exception, code, message, plugin, read, write):
|
||||
game_id = "6"
|
||||
request_id = "55"
|
||||
plugin.prepare_local_size_context.return_value = async_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)]
|
||||
plugin.get_local_size.side_effect = exception
|
||||
await plugin.run()
|
||||
plugin.get_local_size.assert_called()
|
||||
plugin.local_size_import_complete.assert_called_once_with()
|
||||
|
||||
assert get_messages(write) == [
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": request_id,
|
||||
"result": None
|
||||
},
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "local_size_import_failure",
|
||||
"params": {
|
||||
"game_id": game_id,
|
||||
"error": {
|
||||
"code": code,
|
||||
"message": message
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "local_size_import_finished",
|
||||
"params": None
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prepare_get_local_size_context_error(plugin, read, write):
|
||||
request_id = "31415"
|
||||
error_details = "Unexpected syntax"
|
||||
error_message, error_code = FailedParsingManifest().message, FailedParsingManifest().code
|
||||
plugin.prepare_local_size_context.side_effect = FailedParsingManifest(error_details)
|
||||
request = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": request_id,
|
||||
"method": "start_local_size_import",
|
||||
"params": {"game_ids": ["6"]}
|
||||
}
|
||||
read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)]
|
||||
await plugin.run()
|
||||
|
||||
assert get_messages(write) == [
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": request_id,
|
||||
"error": {
|
||||
"code": error_code,
|
||||
"message": error_message,
|
||||
"data": error_details
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@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)
|
||||
requests = [
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "3",
|
||||
"method": "start_local_size_import",
|
||||
"params": {
|
||||
"game_ids": ["42"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "4",
|
||||
"method": "start_local_size_import",
|
||||
"params": {
|
||||
"game_ids": ["13"]
|
||||
}
|
||||
}
|
||||
]
|
||||
read.side_effect = [
|
||||
async_return_value(create_message(requests[0])),
|
||||
async_return_value(create_message(requests[1])),
|
||||
async_return_value(b"", 10)
|
||||
]
|
||||
|
||||
await plugin.run()
|
||||
|
||||
responses = get_messages(write)
|
||||
assert {
|
||||
"jsonrpc": "2.0",
|
||||
"id": "3",
|
||||
"result": None
|
||||
} in responses
|
||||
assert {
|
||||
"jsonrpc": "2.0",
|
||||
"id": "4",
|
||||
"error": {
|
||||
"code": 600,
|
||||
"message": "Import already in progress"
|
||||
}
|
||||
} in responses
|
||||
|
||||
Reference in New Issue
Block a user