1
0
mirror of https://github.com/lutris/lutris synced 2024-07-05 16:38:42 +00:00

Start breaking up version code and add tests

This commit is contained in:
Mathieu Comandon 2024-03-28 12:51:00 -07:00
parent c490ae2a8d
commit 916e8aa0db
4 changed files with 94 additions and 69 deletions

View File

@ -190,8 +190,7 @@ def download_runner_versions(runner_name: str) -> list:
runner_info = None
if not runner_info:
return []
versions = runner_info.get("versions") or []
return versions
return runner_info.get("versions") or []
def format_runner_version(version_info: Dict[str, str]) -> str:
@ -235,6 +234,65 @@ def parse_version_architecture(version_name: str) -> Tuple[str, str]:
return version_name, LINUX_SYSTEM.arch
def get_runner_version_from_cache(runner_name, version):
# Prefer to provide the info from our local cache if we can; if this can't find
# an unambiguous result, we'll fall back on the API which should know what the default is.
version, _arch = parse_version_architecture(version or "")
runtime_versions = get_runtime_versions()
if runtime_versions:
try:
runner_versions = runtime_versions["runners"][runner_name]
runner_versions = [r for r in runner_versions if r["architecture"] in (LINUX_SYSTEM.arch, "all")]
if version:
runner_versions = [r for r in runner_versions if r["version"] == version]
if len(runner_versions) == 1:
return runner_versions[0]
except KeyError:
pass
return None
def iter_get_from_api_candidates(versions: list, version: str, arch: str):
"""A generator yielding possible version infos, or None for those that are available;
we pick the first non-None value yielded."""
def select_info(predicate=None, accept_ambiguous=False):
candidates = [v for v in versions if predicate(v)]
if candidates and (accept_ambiguous or len(candidates) == 1):
return candidates[0]
return None
if version:
yield select_info(lambda v: v["architecture"] == arch and v["version"] == version)
else:
yield select_info(lambda v: v["architecture"] == arch and v["default"])
# Try various fallbacks to get some version - we prefer the default version
# or a version with the right architecture.
yield select_info(lambda v: v["architecture"] == arch and v["default"])
yield select_info(lambda v: v["architecture"] == arch)
# 64-bit system can use 32-bit version, if it's the default.
if LINUX_SYSTEM.is_64_bit:
yield select_info(lambda v: v["default"])
yield select_info(lambda v: v["architecture"] == arch, accept_ambiguous=True)
def get_runner_version_from_api(runner_name: str, version: str):
version, arch = parse_version_architecture(version or "")
versions = download_runner_versions(runner_name)
for candidate in iter_get_from_api_candidates(versions, version, arch):
if candidate:
if not version:
return candidate
if version == candidate.get("version") and arch == candidate.get("architecture"):
return candidate
return None
def get_default_runner_version_info(runner_name: str, version: Optional[str] = None) -> Dict[str, str]:
"""Get the appropriate version for a runner
@ -246,70 +304,7 @@ def get_default_runner_version_info(runner_name: str, version: Optional[str] = N
if the data can't be retrieved. If a pseudo-version is accepted, may be
a dict containing only the version itself.
"""
version, arch = parse_version_architecture(version or "")
def get_from_cache():
# Prefer to provide the info from our local cache if we can; if this can't find
# an unambiguous result, we'll fall back on the API which should know what the default is.
runtime_versions = get_runtime_versions()
if runtime_versions:
try:
runner_versions = runtime_versions["runners"][runner_name]
runner_versions = [r for r in runner_versions if r["architecture"] in (LINUX_SYSTEM.arch, "all")]
if version:
runner_versions = [r for r in runner_versions if r["version"] == version]
if len(runner_versions) == 1:
return runner_versions[0]
except KeyError:
pass
return None
def iter_get_from_api_candidates():
"""A generator yielding possible version infos, or None for those that are available;
we pick the first non-None value yielded."""
versions = download_runner_versions(runner_name)
def select_info(predicate=None, accept_ambiguous=False):
candidates = [v for v in versions if predicate(v)]
if candidates and (accept_ambiguous or len(candidates) == 1):
return candidates[0]
return None
if version:
yield select_info(lambda v: v["architecture"] == arch and v["version"] == version)
else:
yield select_info(lambda v: v["architecture"] == arch and v["default"])
# Try various fallbacks to get some version - we prefer the default version
# or a version with the right architecture.
yield select_info(lambda v: v["architecture"] == arch and v["default"])
yield select_info(lambda v: v["architecture"] == arch)
# 64-bit system can use 32-bit version, if it's the default.
if LINUX_SYSTEM.is_64_bit:
yield select_info(lambda v: v["default"])
yield select_info(lambda v: v["architecture"] == arch, accept_ambiguous=True)
def get_from_api():
logger.info(
"Getting runner information for %s%s",
runner_name,
" (version: %s)" % version if version else "",
)
for candidate in iter_get_from_api_candidates():
if candidate:
if not version:
return candidate
if version == candidate.get("version") and arch == candidate.get("architecture"):
return candidate
return None
return get_from_cache() or get_from_api()
return get_runner_version_from_cache(runner_name, version) or get_runner_version_from_api(runner_name, version)
@cache_single

View File

@ -12,4 +12,4 @@ class TestSnes9x(TestCase):
if snes9x_runner.is_installed():
snes9x_runner.set_option("full_screen_on_open", "1")
else:
LOGGER.info("snes9x not installed, can't run test")
LOGGER.info("snes9x not installed, can't run test")

32
tests/test_api.py Normal file
View File

@ -0,0 +1,32 @@
import unittest
from unittest.mock import patch
from lutris import api
RUNTIME_VERSIONS = {
"client_version": "0.5.17",
"runners": {
"wine": [
{
"name": "wine",
"version": "wine-ge-8-27",
"url": "https://github.com/GloriousEggroll/wine-ge-custom/releases/download/GE-Proton8-26/wine-lutris-GE-Proton8-26-x86_64.tar.xz",
"architecture": "x86_64",
}
],
},
}
class TestApi(unittest.TestCase):
@patch("lutris.api.get_runtime_versions")
def test_get_default_runner_version_info(self, mock_get_runtime_versions):
mock_get_runtime_versions.return_value = RUNTIME_VERSIONS
version_info = api.get_default_runner_version_info("wine")
self.assertEqual(version_info["version"], "wine-ge-8-27")
version_info = api.get_default_runner_version_info("wine", "lutris-7.2-2")
self.assertEqual(version_info["version"], "lutris-7.2-2")
version_info = api.get_default_runner_version_info("wine", "lutris-7.2-2-x86_64")
self.assertEqual(version_info["version"], "lutris-7.2-2")

View File

@ -3,8 +3,6 @@ from unittest import TestCase
from lutris import runners
from lutris.gui.application import Application
from lutris.gui.config.add_game_dialog import AddGameDialog
# from lutris import settings
from lutris.gui.config.game_common import GameDialogCommon
from lutris.gui.views.store import sort_func
from lutris.util.test_config import setup_test_environment