Repository: spyder-ide/spyder

Issue:
IPython: Run Code at Startup - Magics
## Description

**What steps will reproduce the problem?**

1. Start Spyder
2. Open Preferences
3. Select IPython console preferences
4. Select Startup Tab
5. Enter `%load_ext autoreload, %autoreload 2`
6. Click Apply

**What is the expected output? What do you see instead?**

* Expected: Allow these valid IPython magics to be stored in the config and loaded on Console startup
* Actual: The commands cause the error below

**Please provide any additional information below**

  File "C:\Anaconda3\lib\site-packages\spyder\plugins\configdialog.py", line 221, in button_clicked
    configpage.apply_changes()
  File "C:\Anaconda3\lib\site-packages\spyder\plugins\configdialog.py", line 100, in apply_changes
    self.save_to_conf()
  File "C:\Anaconda3\lib\site-packages\spyder\plugins\configdialog.py", line 408, in save_to_conf
    self.set_option(option, to_text_string(lineedit.text()))
  File "C:\Anaconda3\lib\site-packages\spyder\plugins\__init__.py", line 437, in set_option
    CONF.set(self.CONF_SECTION, str(option), value)
  File "C:\Anaconda3\lib\site-packages\spyder\config\user.py", line 443, in set
    self._set(section, option, value, verbose)
  File "C:\Anaconda3\lib\site-packages\spyder\config\user.py", line 86, in _set
    cp.ConfigParser.set(self, section, option, value)
  File "C:\Anaconda3\lib\configparser.py", line 1193, in set
    super().set(section, option, value)
  File "C:\Anaconda3\lib\configparser.py", line 894, in set
    value)
  File "C:\Anaconda3\lib\configparser.py", line 402, in before_set
    "position %d" % (value, tmp_value.find('%')))
ValueError: invalid interpolation syntax in '%load_ext autoreload, %a

**Work Around**
`from IPython import get_ipython, ipython = get_ipython(), ipython.magic("load_ext autoreload"), ipython.magic("autoreload 2")`


Discussion:
@dalthviz, please take a look at this one. We have to find a way to prevent saving strings with `%` in our config system (i.e. in `spyder.ini`).
I had to add some special code around [spyder/plugins/variableexplorer.py:110](https://github.com/spyder-ide/spyder/blob/46db31fbcbc0f5b1c12f2f7b29520422ff06ec8e/spyder/plugins/variableexplorer.py#L110) to remove the `%` at the start of a format string, so that code can probably be streamlined after this is fixed.
Thanks @jitseniesen!

Resolving patch:
diff --git a/spyder/config/user.py b/spyder/config/user.py
--- a/spyder/config/user.py
+++ b/spyder/config/user.py
@@ -48,7 +48,10 @@ class DefaultsConfig(cp.ConfigParser):
     UserConfig
     """
     def __init__(self, name, subfolder):
-        cp.ConfigParser.__init__(self)
+        if PY2:
+            cp.ConfigParser.__init__(self)
+        else:
+            cp.ConfigParser.__init__(self, interpolation=None)
         self.name = name
         self.subfolder = subfolder
 


Test patch:
diff --git a/spyder/config/tests/test_user.py b/spyder/config/tests/test_user.py
--- a/spyder/config/tests/test_user.py
+++ b/spyder/config/tests/test_user.py
@@ -28,6 +28,13 @@ def userconfig(tmpdir, monkeypatch):
     return UserConfig('foo', defaults={}, subfolder=True,
                       version='1.0.0', raw_mode=True)
 
+
+def test_userconfig_set_percentage_string(userconfig):
+    """Test to set an option with a '%'."""
+    userconfig.set('section', 'option', '%value')
+    assert userconfig.get('section', 'option') == '%value'
+
+
 def test_userconfig_get_string_from_inifile(userconfig):
     assert userconfig.get('section', 'option') == 'value'