import contextlib from pathlib import Path import yaml from xdg import xdg_data_home, xdg_config_home from . import consts DEFAULT_CONFIG_DICT = { 'remote_basedir': 'jibril:/storage/games', 'gamesaves_path': Path('~/syncthing/gamesaves').expanduser(), # profile_id: no default for this, only set by user. 'profile_id': None, } def path_relative_to_user(path): # first ensure the path is a Path path = Path(path) with contextlib.suppress(ValueError): return '~' / path.relative_to(Path.home()) # in case the path is not relative to the user home ValueError is raised, # thus we return a fallback value (the path unmodified). return path class GameConfig: def __init__(self): self.config = {} game_config_path = xdg_config_home() / consts.XDG_RESOURCE_NAME game_config_path.mkdir(parents=True, exist_ok=True) game_config_filepath = game_config_path / 'config.yaml' self.game_config_filepath = game_config_filepath with contextlib.ExitStack() as stack: stack.enter_context(contextlib.suppress(FileNotFoundError)) fdin = stack.enter_context(open(game_config_filepath, 'r', encoding='utf8')) self.config = yaml.safe_load(fdin) self.config = { **DEFAULT_CONFIG_DICT, **self.config, } # convert game_saves_path to a path if not already the case (in case # loaded from yaml file). self.config['gamesaves_path'] = ( Path(self.config['gamesaves_path']) .expanduser() ) def get_remote_basedir(self): return self.config['remote_basedir'] def get_gamesaves_path(self): return self.config['gamesaves_path'] def get_games_saves_tools_bin_path(self): return self.get_gamesaves_path() / 'tools' / 'bin' def get_profile_dir(self, profile_id): return self.get_gamesaves_path() / 'profiles' / profile_id def get_games_database_path(self): return self.get_gamesaves_path() / 'gamedata.yaml' def get_data_d(self): return self.get_gamesaves_path() / 'gamedata.yaml.d' def get_profile_id(self): return self.config['profile_id'] def save(self): dict_transformed_for_save = { **self.config } dict_transformed_for_save['gamesaves_path'] = str( path_relative_to_user( self.config['gamesaves_path'] ) ) with open(self.game_config_filepath, 'w', encoding='utf8') as fdout: yaml.safe_dump(dict_transformed_for_save, fdout) def set_profile_id(self, profile_id): self.config['profile_id'] = profile_id def set_remote_basedir(self, remote_basedir): self.config['remote_basedir'] = remote_basedir def set_gamesaves_path(self, path): self.config['gamesaves_path'] = Path(path).expanduser() def get_games_install_basedir(self): games_install_path = ( xdg_data_home() / consts.XDG_RESOURCE_NAME / 'games' ) games_install_path.mkdir(parents=True, exist_ok=True) return games_install_path def print_config(self): print(self.config) # default instance of gameconfig, same instance intended to be shared through # all modules which needs it. config = GameConfig() class GameStatus: def load_yaml(self): with contextlib.ExitStack() as stack: stack.enter_context(contextlib.suppress(FileNotFoundError)) fdin = stack.enter_context(open(self.yaml_path, 'r', encoding='utf8')) data = yaml.safe_load(fdin) self.last_loaded_profile = data.get('last_loaded_profile', self.last_loaded_profile) self.last_loaded_game = data.get('last_loaded_game', self.last_loaded_game) def write_yaml(self): with contextlib.ExitStack() as stack: stack.enter_context(contextlib.suppress(FileNotFoundError)) fdout = stack.enter_context(open(self.yaml_path, 'w', encoding='utf8')) data = { 'last_loaded_profile': self.last_loaded_profile, 'last_loaded_game': self.last_loaded_game, } yaml.safe_dump(data, fdout) def __init__(self): self.yaml_path = ( xdg_data_home() / consts.XDG_RESOURCE_NAME / 'status.yaml' ) self.last_loaded_profile = config.get_profile_id() self.last_loaded_game = None self.load_yaml() def set_last_loaded_profile(self, profile): self.last_loaded_profile = profile self.write_yaml() def set_last_loaded_game(self, game): self.last_loaded_game = game self.write_yaml() status = GameStatus()