Repository: ipython/ipython

Issue:
c.TerminalInteractiveShell.editing_mode = 'vi' breaks in 7.1.0.dev0
This is on MacOS Mojave, using pipenv to install.

Python 3.7.0.

When setting c.TerminalInteractiveShell.editing_mode = 'vi' in the config file, it generates the folllow exception. Setting it to emacs mode works fine. Rolling back to 7.0.0 works fine. 7.1.0.dev0 was installed using pipenv upgrade ipython.

```
Traceback (most recent call last):
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/bin/ipython", line 11, in <module>
    load_entry_point('ipython', 'console_scripts', 'ipython')()
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/src/ipython/IPython/__init__.py", line 125, in start_ipython
    return launch_new_instance(argv=argv, **kwargs)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/config/application.py", line 657, in launch_instance
    app.initialize(argv)
  File "<decorator-gen-112>", line 2, in initialize
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/config/application.py", line 87, in catch_config_error
    return method(app, *args, **kwargs)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/src/ipython/IPython/terminal/ipapp.py", line 317, in initialize
    self.init_shell()
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/src/ipython/IPython/terminal/ipapp.py", line 333, in init_shell
    ipython_dir=self.ipython_dir, user_ns=self.user_ns)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/config/configurable.py", line 412, in instance
    inst = cls(*args, **kwargs)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/src/ipython/IPython/terminal/interactiveshell.py", line 450, in __init__
    super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/src/ipython/IPython/core/interactiveshell.py", line 622, in __init__
    super(InteractiveShell, self).__init__(**kwargs)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/config/configurable.py", line 84, in __init__
    self.config = config
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/traitlets.py", line 585, in __set__
    self.set(obj, value)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/traitlets.py", line 574, in set
    obj._notify_trait(self.name, old_value, new_value)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/traitlets.py", line 1139, in _notify_trait
    type='change',
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/traitlets.py", line 1176, in notify_change
    c(change)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/traitlets.py", line 819, in compatible_observer
    return func(self, change)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/config/configurable.py", line 186, in _config_changed
    self._load_config(change.new, traits=traits, section_names=section_names)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/config/configurable.py", line 168, in _load_config
    warn(msg)
  File "/Users/deankao/.pyenv/versions/3.7.0/lib/python3.7/contextlib.py", line 119, in __exit__
    next(self.gen)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/traitlets.py", line 1131, in hold_trait_notifications
    self.notify_change(change)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/lib/python3.7/site-packages/traitlets/traitlets.py", line 1176, in notify_change
    c(change)
  File "/Users/deankao/.virtualenvs/rarity-wJbxM3QZ/src/ipython/IPython/terminal/interactiveshell.py", line 150, in _editing_mode
    self.pt_app.editing_mode = u_mode
AttributeError: 'NoneType' object has no attribute 'editing_mode'
```


Discussion:
Apologies we added logic to allow switching at runtime. I'll fix that.

Resolving patch:
diff --git a/IPython/terminal/interactiveshell.py b/IPython/terminal/interactiveshell.py
--- a/IPython/terminal/interactiveshell.py
+++ b/IPython/terminal/interactiveshell.py
@@ -147,7 +147,8 @@ def _validate_editing_mode(self, proposal):
     @observe('editing_mode')
     def _editing_mode(self, change):
         u_mode = change.new.upper()
-        self.pt_app.editing_mode = u_mode
+        if self.pt_app:
+            self.pt_app.editing_mode = u_mode
 
     @observe('highlighting_style')
     @observe('colors')


Test patch: