DavidoTek / ProtonUp-Qt

Install and manage GE-Proton, Luxtorpeda & more for Steam and Wine-GE & more for Lutris with this graphical user interface.
https://davidotek.github.io/protonup-qt
GNU General Public License v3.0
1.16k stars 39 forks source link

DuplicateOptionsError (crash on startup) #361

Open B4rabbas opened 4 months ago

B4rabbas commented 4 months ago

Describe the bug
ProtonUpQt crash on startup

To Reproduce
Steps to reproduce the behavior:

  1. Launch the app
  2. See error

Expected behavior
Launching the app witheout crash.

Screenshots
Sorry, there is nothing more than the shell output.

Desktop (please complete the following information):

Additional context
Happen after installing proton in native steam (for my lutris library)

Terminal output

❯ /usr/bin/flatpak run --branch=stable --arch=x86_64 --command=net.davidotek.pupgui2 net.davidotek.pupgui2
ProtonUp-Qt 2.9.1 by DavidoTek. Build Info: DavidoTek Flathub build.
Python 3.10.13 (main, Nov 10 2011, 15:00:00) [GCC 12.2.0], PySide 6.5.2
Platform: KDE Flatpak runtime 6.5 Linux-5.15.0-97-generic-x86_64-with-glibc2.35
Gtk-Message: 19:03:44.820: Failed to load module "xapp-gtk3-module"
Qt: Session management error: Could not open network socket
Loading locale fr / fr_FR
Traceback (most recent call last):
  File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/app/lib/python3.10/site-packages/pupgui2/__main__.py", line 2, in <module>
    main()
  File "/app/lib/python3.10/site-packages/pupgui2/pupgui2.py", line 569, in main
    apply_dark_theme(app)
  File "/app/lib/python3.10/site-packages/pupgui2/util.py", line 88, in apply_dark_theme
    theme = config_theme()
  File "/app/lib/python3.10/site-packages/pupgui2/util.py", line 152, in config_theme
    return read_update_config_value('theme', theme, section='pupgui2')
  File "/app/lib/python3.10/site-packages/pupgui2/util.py", line 138, in read_update_config_value
    config.read(config_file)
  File "/usr/lib/python3.10/configparser.py", line 699, in read
    self._read(fp, filename)
  File "/usr/lib/python3.10/configparser.py", line 1098, in _read
    raise DuplicateOptionError(sectname, optname,
configparser.DuplicateOptionError: While reading from '/home/harry/.var/app/net.davidotek.pupgui2/config/pupgui/config.ini' [line  5]: option 'github_api_token' in section 'pupgui' already exists
DavidoTek commented 4 months ago

configparser.DuplicateOptionError: While reading from '/home/harry/.var/app/net.davidotek.pupgui2/config/pupgui/config.ini' [line 5]: option 'github_api_token' in section 'pupgui' already exists

Did you configure the GitHub API access token? It seems like it is configured twice.

Please edit /home/harry/.var/app/net.davidotek.pupgui2/config/pupgui/config.ini and remove the second github_api_token entry.

Maybe you meant gitlab_api_token instead? (GitLab not GitHub)

B4rabbas commented 4 months ago

Yes, it's fixed.

sonic2kk commented 4 months ago

Is there a (straightforward) way we could manage this better? For example removing duplicate entries, or ignoring them and using the latest?

Assuming the issue above was that github_api_token was defined twice when it was meant to be gitlab_api_token, this would simply mask an issue, as a user would expect the GitLab token to be defined and it wouldn't be. But maybe handling it in some way is better than a crash? This crash afaict comes from the library we use but maybe there's something we can configure?

Then again , maybe not worth it since the long-term plan is to allow this to be configurable from the UI.

sonic2kk commented 4 months ago

I had a look into this, we could catch configparser.DuplicateOptionError, but we'd have to do this in a few places.

Mostly when we read from the config file in util.py, we use read_update_config_value (introduced as part of #306). There was, as far as I recall, an explicit decision to not use read_update_config_value in certain places, because a refactor could end up being a bit unwieldy. So there are two places where we still interact with the config file directly:

In order to catch this error, we would need to make adjustments in the following places (how we want to handle the exception is a different story):

So that covers where we need to make the changes, and how we coulld do it. Basically just wrap these interactions with the config file in a try/except that catches DuplicateOperationError.

If we go forward with this, the question becomes how we want to handle this. There are some ideas I have:

Personally, I think showing a more human-readable dialog to override the existing dialog, which just pulls in the stacktrace (#313), to better inform the user of what actually went wrong, is a step in the right direction. The two problems here are:

DavidoTek commented 4 months ago

This one is straightforward, we can just wrap the function in a try/except DuplicateOptionError block. Show a slightly more user-friendly error. Instead of a stack trace, we could show a dialog and print that some key in the config file is duplicated. In read_update_config_value, we have the section and option, so we could offer a guess to the user as to what key is duplicated in what section.

Feels a bit sketchy, but we could do something like this:

try:
    # config code
except DuplicateOperationError:
    raise Exception("Hello, this is a user friendly error message")

Or ideally just show a message box and then load a default config from constants.py or something.

If we go forward with this, the question becomes how we want to handle this

I should note that the user should know how to edit the config as duplicate keys were introduced by the user before.

but if we could read and remove duplicate keys, that might be an option to do after warning about the duplicate values

Removing the duplicate key would probably be the most user friendly option although we would need to remove both instances as we don't know which one is correct and then let the user know.

Alternatively, there could be a dialog with the buttons: Okay, just delete the config for me and Exit, I will fix it myself.

Is this even worth exploring? Maybe we'd be better putting effort into refactoring the "About" menu into an "Options" menu, and exposing the config options on the UI. That way, we should be able to avoid duplicate entries in the config file in the first place. Although there's no reason we can't do both.

Seems to the the most logical option...


I feel like the way to go is:

sonic2kk commented 3 months ago

I like the "delete" option. This kind of issue should never happen from our side (we always use ConfigParser, and it's unlikely to cause a problem) so I think having the option to just start over or let the user investigate is good.