Repository: ipython/ipython

Issue:
sys.path missing `''` as first entry when kernel launched without interface
Quite simply, if I launch `ipython` or `ipython console` or `ipython qtconsole`, then `import sys`, it should be the case that `sys.path[0]` is `''`, so that modules in the current directory can be found, just like in a standard python session. However, if I begin by launching `ipython kernel`, and then attach a console/qtconsole to the kernel, this item is not in `sys.path`, so modules in the current directory cannot be imported (unless the current directory is in `$PYTHONPATH` to start with). To confirm, this bug is not present if I launch a console/qtconsole and then attach another interface to the existing session.



Discussion:
Indeed, [here is the line](https://github.com/ipython/ipython/blob/master/IPython/frontend/terminal/ipapp.py#L322) where we handle this in regular IPython.  It is not duplicated in the ShellApp parent, where it should be such that any entry point would inherit it.


Resolving patch:
diff --git a/IPython/core/shellapp.py b/IPython/core/shellapp.py
--- a/IPython/core/shellapp.py
+++ b/IPython/core/shellapp.py
@@ -117,9 +117,10 @@ class InteractiveShellApp(Configurable):
     
     Provides configurables for loading extensions and executing files
     as part of configuring a Shell environment.
-    
-    Provides init_extensions() and init_code() methods, to be called
-    after init_shell(), which must be implemented by subclasses.
+
+    Provides init_path(), to be called before, and init_extensions() and
+    init_code() methods, to be called after init_shell(), which must be
+    implemented by subclasses.
     """
     extensions = List(Unicode, config=True,
         help="A list of dotted module names of IPython extensions to load."
@@ -156,6 +157,11 @@ def _extra_extension_changed(self, name, old, new):
     )
     shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
 
+    def init_path(self):
+        """Add current working directory, '', to sys.path"""
+        if sys.path[0] != '':
+            sys.path.insert(0, '')
+
     def init_shell(self):
         raise NotImplementedError("Override in subclasses")
     
diff --git a/IPython/frontend/terminal/ipapp.py b/IPython/frontend/terminal/ipapp.py
--- a/IPython/frontend/terminal/ipapp.py
+++ b/IPython/frontend/terminal/ipapp.py
@@ -314,6 +314,7 @@ def initialize(self, argv=None):
         # print self.extra_args
         if self.extra_args and not self.something_to_run:
             self.file_to_run = self.extra_args[0]
+        self.init_path()
         # create the shell
         self.init_shell()
         # and draw the banner
@@ -325,10 +326,6 @@ def initialize(self, argv=None):
 
     def init_shell(self):
         """initialize the InteractiveShell instance"""
-        # I am a little hesitant to put these into InteractiveShell itself.
-        # But that might be the place for them
-        sys.path.insert(0, '')
-
         # Create an InteractiveShell instance.
         # shell.display_banner should always be False for the terminal
         # based app, because we call shell.show_banner() by hand below
diff --git a/IPython/zmq/ipkernel.py b/IPython/zmq/ipkernel.py
--- a/IPython/zmq/ipkernel.py
+++ b/IPython/zmq/ipkernel.py
@@ -597,6 +597,7 @@ class IPKernelApp(KernelApp, InteractiveShellApp):
     @catch_config_error
     def initialize(self, argv=None):
         super(IPKernelApp, self).initialize(argv)
+        self.init_path()
         self.init_shell()
         self.init_extensions()
         self.init_code()


Test patch: