Skip to content

Commit

Permalink
Add vdf_safe_load function (#455)
Browse files Browse the repository at this point in the history
* steamutil: Implement vdf_safe_load

* Replace vdf.load(...) with vdf_safe_load(...)
  • Loading branch information
DavidoTek authored Sep 20, 2024
1 parent cca7846 commit 1f385df
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 22 deletions.
4 changes: 3 additions & 1 deletion pupgui2/datastructures.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,9 @@ def get_internal_name(self) -> str:
"""
compat_tool_vdf_path = os.path.join(self.install_dir, self.install_folder, 'compatibilitytool.vdf')
if os.path.exists(compat_tool_vdf_path):
compat_tool_vdf = vdf.load(open(compat_tool_vdf_path))
# TODO: Move this somewhere else and use steamutil.py#vdf_safe_load
with open(compat_tool_vdf_path, 'r', encoding='utf-8', errors='replace') as f:
compat_tool_vdf = vdf.loads(f.read())
if 'compatibilitytools' in compat_tool_vdf and 'compat_tools' in compat_tool_vdf['compatibilitytools']:
return list(compat_tool_vdf['compatibilitytools']['compat_tools'].keys())[0]

Expand Down
60 changes: 39 additions & 21 deletions pupgui2/steamutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ def get_steam_app_list(steam_config_folder: str, cached=False, no_shortcuts=Fals
apps = []

try:
v = vdf.load(open(libraryfolders_vdf_file))
c = get_steam_vdf_compat_tool_mapping(vdf.load(open(config_vdf_file)))
v = vdf_safe_load(libraryfolders_vdf_file)
c = get_steam_vdf_compat_tool_mapping(vdf_safe_load(config_vdf_file))

for fid in v.get('libraryfolders'):
if 'apps' not in v.get('libraryfolders').get(fid):
Expand All @@ -73,7 +73,7 @@ def get_steam_app_list(steam_config_folder: str, cached=False, no_shortcuts=Fals
fid_steamapps_path = os.path.join(fid_libraryfolder_path, 'steamapps') # e.g. /home/gaben/Games/steamapps
appmanifest_path = os.path.join(fid_steamapps_path, f'appmanifest_{appid}.acf')
if os.path.isfile(appmanifest_path):
appmanifest_install_path = vdf.load(open(appmanifest_path)).get('AppState', {}).get('installdir', None)
appmanifest_install_path = vdf_safe_load(appmanifest_path).get('AppState', {}).get('installdir', None)
if not appmanifest_install_path or not os.path.isdir(os.path.join(fid_steamapps_path, 'common', appmanifest_install_path)):
continue

Expand Down Expand Up @@ -111,7 +111,7 @@ def get_steam_shortcuts_list(steam_config_folder: str, compat_tools: dict=None)

try:
if not compat_tools:
compat_tools = get_steam_vdf_compat_tool_mapping(vdf.load(open(config_vdf_file)))
compat_tools = get_steam_vdf_compat_tool_mapping(vdf_safe_load(config_vdf_file))

for userf in os.listdir(users_folder):
user_directory = os.path.join(users_folder, userf)
Expand Down Expand Up @@ -218,7 +218,7 @@ def get_steam_global_ctool_name(steam_config_folder: str) -> str:
"""

config_vdf_file = os.path.join(os.path.expanduser(steam_config_folder), 'config.vdf')
d = get_steam_vdf_compat_tool_mapping(vdf.load(open(config_vdf_file)))
d = get_steam_vdf_compat_tool_mapping(vdf_safe_load(config_vdf_file))

return d.get('0', {}).get('name', '')

Expand Down Expand Up @@ -388,7 +388,7 @@ def steam_update_ctool(game: SteamApp, new_ctool=None, steam_config_folder='') -
game_id = game.app_id

try:
d = vdf.load(open(config_vdf_file))
d = vdf_safe_load(config_vdf_file)
c = get_steam_vdf_compat_tool_mapping(d)

if str(game_id) in c:
Expand Down Expand Up @@ -417,7 +417,7 @@ def steam_update_ctools(games: Dict[SteamApp, str], steam_config_folder='') -> b
return False

try:
d = vdf.load(open(config_vdf_file))
d = vdf_safe_load(config_vdf_file)
c = get_steam_vdf_compat_tool_mapping(d)

for game, new_ctool in games.items():
Expand Down Expand Up @@ -751,20 +751,19 @@ def get_steam_user_list(steam_config_folder: str) -> List[SteamUser]:
return []

try:
with open(loginusers_vdf_file) as f:
d = vdf.load(f)
u = d.get('users', {})
for uid in list(u.keys()):
uvalue = u.get(uid, {})

user = SteamUser()
user.long_id = int(uid)
user.account_name = uvalue.get('AccountName', '')
user.persona_name = uvalue.get('PersonaName', '')
user.most_recent = bool(int(uvalue.get('MostRecent', '0')))
user.timestamp = int(uvalue.get('Timestamp', '-1'))

users.append(user)
d = vdf_safe_load(loginusers_vdf_file)
u = d.get('users', {})
for uid in list(u.keys()):
uvalue = u.get(uid, {})

user = SteamUser()
user.long_id = int(uid)
user.account_name = uvalue.get('AccountName', '')
user.persona_name = uvalue.get('PersonaName', '')
user.most_recent = bool(int(uvalue.get('MostRecent', '0')))
user.timestamp = int(uvalue.get('Timestamp', '-1'))

users.append(user)
except Exception as e:
print('Error: Could not get a list of Steam users:', e)

Expand Down Expand Up @@ -809,3 +808,22 @@ def is_valid_steam_install(steam_path) -> bool:
is_valid_steam_install = os.path.exists(config_vdf) and os.path.exists(libraryfolders_vdf)

return is_valid_steam_install

def vdf_safe_load(vdf_file: str) -> dict:
"""
Loads a vdf file and returns its contents as a dict.
In case of an error, the error is printed and {} is returned.
Args:
vdf_file (str): Path to the vdf file
Returns:
dict
"""

try:
# See https://github.com/DavidoTek/ProtonUp-Qt/issues/424 (unicode errors)
with open(vdf_file, 'r', encoding='utf-8', errors='replace') as f:
return vdf.loads(f.read())
except Exception as e:
print(f'An error occured while calling vdf_safe_load({vdf_file}): {e}')

0 comments on commit 1f385df

Please sign in to comment.