Repository: spyder-ide/spyder
Pull request: PR: Prompt user to reset Spyder config files in case `CONF` instance initialization fails
<!--- Make sure to read the Contributing Guidelines:                   --->
<!--- https://github.com/spyder-ide/spyder/blob/master/CONTRIBUTING.md --->
<!--- and follow PEP 8, PEP 257 and Spyder's code style:               --->
<!--- https://github.com/spyder-ide/spyder/wiki/Dev:-Coding-Style      --->

## Description of Changes


* [ ] Wrote at least one-line docstrings (for any new functions)
* [ ] Added unit test(s) covering the changes (if testable)
<!--- Remember that an image/animation is worth a thousand words! --->
* [x] Included a screenshot or animation (if affecting the UI, see [Licecap](https://www.cockos.com/licecap/))


<!--- Explain what you've done and why --->

Handle error when creating the `CONF` instance by showing reset config files message:

![imagen](https://user-images.githubusercontent.com/16781833/159741472-d95a446f-0a3c-4e3e-969c-28ceb5ec17fe.png)

![imagen](https://user-images.githubusercontent.com/16781833/159741510-df1a683b-8532-49cd-ab7a-7b813323abd6.png)


### Issue(s) Resolved

<!--- List the issue(s) below, in the form "Fixes #1234"; one per line --->

Fixes #16747 


### Affirmation

By submitting this Pull Request or typing my (user)name below,
I affirm the [Developer Certificate of Origin](https://developercertificate.org)
with respect to all commits and content included in this PR,
and understand I am releasing the same under Spyder's MIT (Expat) license.

<!--- TYPE YOUR USER/NAME AFTER THE FOLLOWING: --->
I certify the above statement is true and correct: dalthviz

<!--- Thanks for your help making Spyder better for everyone! --->


Problem statement:
Error when loading configuration file
I can't open Spyder via Anaconda, if i want to start spyder, the loading bar will apear but after that nothing happen. Also if i want to update it to a newer version like 5.0.5, it will load until infinity.

If i want to open spyder via the terminal, this will appear:

(base) C:\Users\fuzhan>spyder
Traceback (most recent call last):
File "C:\Users\fuzhan\anaconda3\Scripts\spyder-script.py", line 10, in
sys.exit(main())
File "C:\Users\fuzhan\anaconda3\lib\site-packages\spyder\app\start.py", line 97, in main
from spyder.config.manager import CONF
File "C:\Users\fuzhan\anaconda3\lib\site-packages\spyder\config\manager.py", line 351, in
CONF = ConfigurationManager()
File "C:\Users\fuzhan\anaconda3\lib\site-packages\spyder\config\manager.py", line 64, in init
self._user_config = MultiUserConfig(
File "C:\Users\fuzhan\anaconda3\lib\site-packages\spyder\config\user.py", line 782, in init
self._configs_map[name] = config_class(**new_kwargs)
File "C:\Users\fuzhan\anaconda3\lib\site-packages\spyder\config\user.py", line 212, in init
self._load_from_ini(previous_fpath)
File "C:\Users\fuzhan\anaconda3\lib\site-packages\spyder\config\user.py", line 333, in _load_from_ini
self.read(fpath, encoding='utf-8')
File "C:\Users\fuzhan\anaconda3\lib\configparser.py", line 697, in read
self._read(fp, filename)
File "C:\Users\fuzhan\anaconda3\lib\configparser.py", line 1067, in _read
raise DuplicateSectionError(sectname, fpname,
configparser.DuplicateSectionError: While reading from 'C:\Users\fuzhan\.spyder-py3\config\transient.ini' [line 117]: section 'find_in_files' already exists

I have already deleted spyder, as well as anaconda and installed it new, but nothing changed.

Ps. i hope i posted this issue in the right category, i am new in GitHub.

Hints from issue discussion:
Hey @Programmfailer, thanks for reporting. Please run the following command in the Anaconda Prompt:

    spyder --reset

and after that, start Spyder again. That should solve your problem.

Let us know if it works for you. 
Note: we should catch and load our default config with this kind of errors because there's nothing else users can do about them than resetting their preferences.
thanks for your help, the reset worked.
Great! I'm reopening this because we plan to do this automatically in one of our next versions. 
@dalthviz, this is a serious bug because any error when loading/reading our config files generates a crash at startup. My idea to solve this is catching those errors and load our default config values instead.
So in case of errors loading/reading the config should get resetted (probably showing a dialog saying to the user that in order to continue the config should be resetted)? Or just the load?

Probably If you load the default values but you don't reset the config then the config causing the error will not be removed and probably when trying to write to the config files more errors could arise, right?
> Probably If you load the default values but you don't reset the config then the config causing the error will not be removed and probably when trying to write to the config files more errors could arise, right?

Yeah, that's a very good point. In Spyder 3 we were simply loading the default config instead of resetting it. But, as you said, that will never fix the underlying error.

So I agree with you and now I think we need the reset the user's config and inform them with a dialog that we needed to do that because their previous configuration was broken.

Commit message: Config: Create QApplication to show config files reset messages

Patch to review:
diff --git a/spyder/config/manager.py b/spyder/config/manager.py
index 30179eb1740..3bf8ceea80b 100644
--- a/spyder/config/manager.py
+++ b/spyder/config/manager.py
@@ -15,9 +15,13 @@
 from typing import Any, Dict, Optional, Set
 import weakref
 
+# Third-party imports
+from qtpy.QtWidgets import QMessageBox
+
 # Local imports
 from spyder.api.utils import PrefixedTuple
-from spyder.config.base import _, get_conf_paths, get_conf_path, get_home_dir
+from spyder.config.base import (
+    _, get_conf_paths, get_conf_path, get_home_dir, reset_config_files)
 from spyder.config.main import CONF_VERSION, DEFAULTS, NAME_MAP
 from spyder.config.types import ConfigurationKey, ConfigurationObserver
 from spyder.config.user import UserConfig, MultiUserConfig, NoDefault, cp
@@ -637,4 +641,21 @@ def reset_shortcuts(self):
             plugin_config.reset_to_defaults(section='shortcuts')
 
 
-CONF = ConfigurationManager()
+try:
+    CONF = ConfigurationManager()
+except Exception:
+    from spyder.app.utils import create_application
+    app = create_application()
+    reset_reply = QMessageBox.critical(
+        None, 'Spyder',
+        _("Error loading Spyder's preferences manager. "
+          "You will need to reset Spyder configuration files "
+          "for Spyder to be able to launch.\n\n"
+          "Reset the Spyder configuration files now?"),
+        QMessageBox.Yes, QMessageBox.No)
+    if reset_reply == QMessageBox.Yes:
+        reset_config_files()
+        QMessageBox.information(
+            None, 'Spyder',
+            _("Spyder configuration files resetted!"))
+    os._exit(0)


Code review comments:
diff_hunk: @@ -637,4 +641,21 @@ def reset_shortcuts(self):
             plugin_config.reset_to_defaults(section='shortcuts')
 
 
-CONF = ConfigurationManager()
+try:
+    CONF = ConfigurationManager()
+except Exception:
+    from spyder.app.utils import create_application
+    app = create_application()
+    reset_reply = QMessageBox.critical(
+        None, 'Spyder',
+        _("Error loading Spyder's preferences manager. "
+          "You will need to reset Spyder configuration files "
+          "for Spyder to be able to launch.\n\n"
+          "Reset the Spyder configuration files now?"),
path: spyder/config/manager.py
text: @user1:
My suggestion for this message:

> There was an error while loading Spyder configuration options. You need to reset them for Spyder to be able to launch.\n\n
> Do you want to proceed?

diff_hunk: @@ -15,9 +15,13 @@
 from typing import Any, Dict, Optional, Set
 import weakref
 
+# Third-party imports
+from qtpy.QtWidgets import QMessageBox
path: spyder/config/manager.py
text: @user1:
Please move this import to be inside the `Exception` you added below because this file is imported in `spyder/app/start.py` and the idea is to avoid indirect Qt imports there, so Spyder starts quickly.