🚧 Various fixes

- Platform-dependent sources
- Added heroic schema keys
- Moved location and is_installed to Source
This commit is contained in:
GeoffreyCoulaud
2023-05-31 22:43:30 +02:00
parent ed66109404
commit 97b770cbf2
5 changed files with 81 additions and 85 deletions

View File

@@ -44,8 +44,14 @@
<default>true</default>
</key>
<key name="heroic-location" type="s">
<default>"~/.config/heroic/"</default>
</key>
<key name="heroic-flatpak-location" type="s">
<default>"~/.var/app/com.heroicgameslauncher.hgl/config/heroic/"</default>
</key>
<key name="heroic-windows-location" type="s">
<default>""</default>
</key>
<key name="heroic-import-epic" type="b">
<default>true</default>
</key>
@@ -92,11 +98,11 @@
</key>
<key name="sort-mode" type="s">
<choices>
<choice value="a-z"/>
<choice value="z-a"/>
<choice value="newest"/>
<choice value="oldest"/>
<choice value="last_played"/>
<choice value="a-z" />
<choice value="z-a" />
<choice value="newest" />
<choice value="oldest" />
<choice value="last_played" />
</choices>
<default>"a-z"</default>
</key>

View File

@@ -1,5 +1,5 @@
import json
from abc import abstractmethod
import logging
from hashlib import sha256
from json import JSONDecodeError
from pathlib import Path
@@ -8,7 +8,7 @@ from typing import Generator, Optional, TypedDict
from src import shared
from src.game import Game
from src.importer.sources.source import Source, SourceIterator
from src.importer.sources.source import NTSource, PosixSource, Source, SourceIterator
from src.utils.decorators import (
replaced_by_env_path,
replaced_by_path,
@@ -87,9 +87,9 @@ class HeroicSourceIterator(SourceIterator):
def sub_sources_generator(self):
"""Generator method producing games from all the Heroic sub-sources"""
for key, sub_source in self.sub_sources.items():
for _key, sub_source in self.sub_sources.items():
# Skip disabled sub-sources
if not shared.schema.get_boolean("heroic-import-" + key):
if not shared.schema.get_boolean("heroic-import-" + sub_source["service"]):
continue
# Load games from JSON
try:
@@ -124,32 +124,19 @@ class HeroicSource(Source):
name = "Heroic"
executable_format = "xdg-open heroic://launch/{app_name}"
@property
@abstractmethod
def location(self) -> Path:
pass
@property
def game_id_format(self) -> str:
"""The string format used to construct game IDs"""
return self.name.lower() + "_{service}_{game_id}"
@property
def is_installed(self):
# pylint: disable=pointless-statement
try:
self.location
except FileNotFoundError:
return False
return True
def __iter__(self):
return HeroicSourceIterator(source=self)
class HeroicNativeSource(HeroicSource):
class HeroicNativeSource(HeroicSource, PosixSource):
variant = "native"
@property
@replaced_by_schema_key("heroic-location")
@replaced_by_env_path("XDG_CONFIG_HOME", "heroic/")
@replaced_by_path("~/.config/heroic/")
@@ -157,19 +144,21 @@ class HeroicNativeSource(HeroicSource):
raise FileNotFoundError()
class HeroicFlatpakSource(HeroicSource):
class HeroicFlatpakSource(HeroicSource, PosixSource):
variant = "flatpak"
@property
@replaced_by_schema_key("heroic-flatpak-location")
@replaced_by_path("~/.var/app/com.heroicgameslauncher.hgl/config/heroic/")
def location(self) -> Path:
raise FileNotFoundError()
class HeroicWindowsSource(HeroicSource):
class HeroicWindowsSource(HeroicSource, NTSource):
variant = "windows"
executable_format = "start heroic://launch/{app_name}"
@property
@replaced_by_schema_key("heroic-windows-location")
@replaced_by_env_path("appdata", "heroic/")
def location(self) -> Path:

View File

@@ -1,11 +1,9 @@
from abc import abstractmethod
from pathlib import Path
from sqlite3 import connect
from time import time
from src import shared
from src.game import Game
from src.importer.sources.source import Source, SourceIterator
from src.importer.sources.source import PosixSource, Source, SourceIterator
from src.utils.decorators import replaced_by_path, replaced_by_schema_key
from src.utils.save_cover import resize_cover, save_cover
@@ -78,29 +76,15 @@ class LutrisSource(Source):
name = "Lutris"
executable_format = "xdg-open lutris:rungameid/{game_id}"
@property
@abstractmethod
def location(self) -> Path:
pass
@property
def game_id_format(self):
return super().game_id_format + "_{game_internal_id}"
@property
def is_installed(self):
# pylint: disable=pointless-statement
try:
self.location
except FileNotFoundError:
return False
return True
def __iter__(self):
return LutrisSourceIterator(source=self)
class LutrisNativeSource(LutrisSource):
class LutrisNativeSource(LutrisSource, PosixSource):
variant = "native"
@property
@@ -110,7 +94,7 @@ class LutrisNativeSource(LutrisSource):
raise FileNotFoundError()
class LutrisFlatpakSource(LutrisSource):
class LutrisFlatpakSource(LutrisSource, PosixSource):
variant = "flatpak"
@property

View File

@@ -1,5 +1,7 @@
import os
from abc import abstractmethod
from collections.abc import Iterable, Iterator
from pathlib import Path
from typing import Optional
from src.game import Game
@@ -30,6 +32,11 @@ class Source(Iterable):
name: str
variant: str
available_on: set[str]
def __init__(self) -> None:
super().__init__()
self.available_on = set()
@property
def full_name(self) -> str:
@@ -52,16 +59,41 @@ class Source(Iterable):
"""The string format used to construct game IDs"""
return self.name.lower() + "_{game_id}"
@property
def is_installed(self):
# pylint: disable=pointless-statement
try:
self.location
except FileNotFoundError:
return False
return os.name in self.available_on
@property
@abstractmethod
def location(self) -> Path:
"""The source's location on disk"""
@property
@abstractmethod
def executable_format(self) -> str:
"""The executable format used to construct game executables"""
@property
@abstractmethod
def is_installed(self) -> bool:
"""Whether the source is detected as installed"""
@abstractmethod
def __iter__(self) -> SourceIterator:
"""Get the source's iterator, to use in for loops"""
class NTSource(Source):
"""Mixin for sources available on Windows"""
def __init__(self) -> None:
super().__init__()
self.available_on.add("nt")
class PosixSource(Source):
"""Mixin for sources available on POXIX-compliant systems"""
def __init__(self) -> None:
super().__init__()
self.available_on.add("posix")

View File

@@ -1,12 +1,11 @@
import re
from abc import abstractmethod
from pathlib import Path
from time import time
from typing import Iterator
from src import shared
from src.game import Game
from src.importer.sources.source import Source, SourceIterator
from src.importer.sources.source import NTSource, PosixSource, Source, SourceIterator
from src.utils.decorators import (
replaced_by_env_path,
replaced_by_path,
@@ -94,25 +93,11 @@ class SteamSource(Source):
name = "Steam"
executable_format = "xdg-open steam://rungameid/{game_id}"
@property
@abstractmethod
def location(self) -> Path:
pass
@property
def is_installed(self):
# pylint: disable=pointless-statement
try:
self.location
except FileNotFoundError:
return False
return True
def __iter__(self):
return SteamSourceIterator(source=self)
class SteamNativeSource(SteamSource):
class SteamNativeSource(SteamSource, PosixSource):
variant = "native"
@property
@@ -124,7 +109,7 @@ class SteamNativeSource(SteamSource):
raise FileNotFoundError()
class SteamFlatpakSource(SteamSource):
class SteamFlatpakSource(SteamSource, PosixSource):
variant = "flatpak"
@property
@@ -134,7 +119,7 @@ class SteamFlatpakSource(SteamSource):
raise FileNotFoundError()
class SteamWindowsSource(SteamSource):
class SteamWindowsSource(SteamSource, NTSource):
variant = "windows"
executable_format = "start steam://rungameid/{game_id}"